Skip to content

Instantly share code, notes, and snippets.

@ologe
Last active July 13, 2023 10:25
Show Gist options
  • Star 21 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save ologe/eaa1dea1f94cdda1a39adcaf3886658a to your computer and use it in GitHub Desktop.
Save ologe/eaa1dea1f94cdda1a39adcaf3886658a to your computer and use it in GitHub Desktop.
Android shared preference observer using kotlin coroutines (1.3.0)
inline fun <reified T> SharedPreferences.observeKey(key: String, default: T): Flow<T> {
val flow = MutableStateFlow(getItem(key, default))
val listener = SharedPreferences.OnSharedPreferenceChangeListener { _, k ->
if (key == k) {
flow.value = getItem(key, default)!!
}
}
registerOnSharedPreferenceChangeListener(listener)
return flow
.onCompletion { unregisterOnSharedPreferenceChangeListener(listener) }
}
inline fun <reified T> SharedPreferences.getItem(key: String, default: T): T {
@Suppress("UNCHECKED_CAST")
return when (default){
is String -> getString(key, default) as T
is Int -> getInt(key, default) as T
is Long -> getLong(key, default) as T
is Boolean -> getBoolean(key, default) as T
is Float -> getFloat(key, default) as T
is Set<*> -> getStringSet(key, default as Set<String>) as T
is MutableSet<*> -> getStringSet(key, default as MutableSet<String>) as T
else -> throw IllegalArgumentException("generic type not handle ${T::class.java.name}")
}
}
@mobilekosmos
Copy link

I came with this solution:

    private fun SharedPreferences.userIdFlow(key: String, defValue: String?): Flow<String?> = callbackFlow {
        var currentValue = getString(key, defValue)

        val listener = SharedPreferences.OnSharedPreferenceChangeListener { _, k ->
            if (k == key) {
                val newValue = getString(key, defValue)
                if (newValue != currentValue) {
                    currentValue = newValue
                    trySend(newValue).isSuccess
                }
            }
        }

        registerOnSharedPreferenceChangeListener(listener)
        if (currentValue != null && currentValue!!.isNotEmpty()) {
            trySend(currentValue).isSuccess // emit current value immediately if not null and not empty
        }

        awaitClose { unregisterOnSharedPreferenceChangeListener(listener) }
    }

What's your analysis on it compared to yours?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment