Skip to content

Instantly share code, notes, and snippets.

@ologe
Last active November 13, 2024 21:10
Show Gist options
  • 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> = channelFlow {
send(getItem(key, default))
val listener = SharedPreferences.OnSharedPreferenceChangeListener { _, k ->
if (key == k) {
trySend(getItem(key, default))
}
}
registerOnSharedPreferenceChangeListener(listener)
awaitClose {
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
else -> error("generic type not handled ${T::class.java.name}")
}
}
@ologe
Copy link
Author

ologe commented Nov 13, 2024

@ubuntudroid yeah probably handling MutableSet is not actually needed, I think the initial thought was that kotlin.collection.MutableSet translated into java.util.Set

btw about switching dispatcher, I think is unnecessary because if I remember correctly SharedPreferences is just a glorified HashMap, and everything is stored (additionally) in memory, the expensive part of the api is writing to disk


I'm also updating the gist to what I think is the cleanest way after almost 4 years 😄

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