Skip to content

Instantly share code, notes, and snippets.

@milis92
Last active December 14, 2021 09:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save milis92/f424f52080ba098d9a031ff013325a5a to your computer and use it in GitHub Desktop.
Save milis92/f424f52080ba098d9a031ff013325a5a to your computer and use it in GitHub Desktop.
package com.ivan.store
import android.content.SharedPreferences
import androidx.core.content.edit
interface KeyValueStore {
fun write(key: String, value: Any?)
fun <T> read(key: String): T?
fun remove(key: String)
fun prune()
fun contains(key: String): Boolean
fun all(): Map<String, Any?>
fun registerObserver(keyValueStoreListener: KeyValueStoreListener)
fun unregisterObserver(keyValueStoreListener: KeyValueStoreListener)
}
fun KeyValueStore.getKeysWithPrefix(prefix: String) =
all().filter { it.key.startsWith(prefix) }.keys
fun KeyValueStore.removeWithPrefix(prefix: String) {
runCatching {
getKeysWithPrefix(prefix).forEach { remove(it) }
}
}
fun KeyValueStore.doOnce(key: String, action: () -> Unit) {
if (read<Any>(key) == null) {
write(key, true)
action()
}
}
class KeyValueStoreListener(
private val valuesFilter: (key: String) -> Boolean,
private val onValueChanged: (key: String) -> Unit
) {
companion object {
fun forKeys(keys: List<String>, onValueChanged: (key: String) -> Unit) =
KeyValueStoreListener(
valuesFilter = { keys.contains(it) },
onValueChanged = onValueChanged
)
}
internal val preferenceListener by lazy {
SharedPreferences.OnSharedPreferenceChangeListener { _, key ->
if (valuesFilter(key)) onValueChanged(key)
}
}
}
internal class SharedPreferencesKeyValueStore(
private val sharedPreferences: SharedPreferences
) : KeyValueStore {
override fun write(key: String, value: Any?) =
sharedPreferences.edit {
when (value) {
is String -> putString(key, value)
is Boolean -> putBoolean(key, value)
is Int -> putInt(key, value)
is Float -> putFloat(key, value)
is Long -> putLong(key, value)
is Set<*> -> putStringSet(key, value.map { it.toString() }.toSet())
}
}
fun write(key: String, value: Set<String?>) {
sharedPreferences.edit {
putStringSet(key, value)
}
}
@Suppress("UNCHECKED_CAST")
override fun <T> read(key: String): T? {
return kotlin.runCatching { sharedPreferences.all[key] as? T? }.getOrNull()
}
override fun remove(key: String) {
sharedPreferences.edit {
remove(key)
}
}
override fun prune() {
sharedPreferences.edit {
clear()
}
}
override fun contains(key: String): Boolean {
return sharedPreferences.contains(key)
}
override fun all(): Map<String, Any?> {
return sharedPreferences.all ?: emptyMap()
}
override fun registerObserver(keyValueStoreListener: KeyValueStoreListener) {
sharedPreferences.registerOnSharedPreferenceChangeListener(
keyValueStoreListener.preferenceListener
)
}
override fun unregisterObserver(keyValueStoreListener: KeyValueStoreListener) {
sharedPreferences.unregisterOnSharedPreferenceChangeListener(
keyValueStoreListener.preferenceListener
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment