Skip to content

Instantly share code, notes, and snippets.

@handstandsam
Last active August 4, 2023 06:12
Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save handstandsam/3d5d7e3decd09057202adb05928bd63f to your computer and use it in GitHub Desktop.
Save handstandsam/3d5d7e3decd09057202adb05928bd63f to your computer and use it in GitHub Desktop.
Shared Preferences is an Interface, so we can back that interface by an "In Memory" version that never persists anything to the file system. I googled around and the closest thing I found was https://gist.github.com/amardeshbd/354173d00b988574ee5019c4ba0c8a0b
import android.content.SharedPreferences
/**
* In Memory implementation of [SharedPreferences], which just transiently saves data in memory, backed by a [MutableMap].
*/
class InMemorySharedPreferences : SharedPreferences {
private val preferenceValuesMap = mutableMapOf<String, Any?>()
private val changeListeners = mutableListOf<SharedPreferences.OnSharedPreferenceChangeListener>()
override fun getAll(): Map<String, Any?> {
return preferenceValuesMap
}
override fun getString(key: String, defaultValue: String?): String? {
return preferenceValuesMap[key] as String? ?: defaultValue
}
override fun getStringSet(key: String, defaultValues: Set<String>?): Set<String>? {
return preferenceValuesMap[key] as Set<String>? ?: defaultValues
}
override fun getInt(key: String, defaultValue: Int): Int {
return preferenceValuesMap[key] as Int? ?: defaultValue
}
override fun getLong(key: String, defaultValue: Long): Long {
return preferenceValuesMap[key] as Long? ?: defaultValue
}
override fun getFloat(key: String, defaultValue: Float): Float {
return preferenceValuesMap[key] as Float? ?: defaultValue
}
override fun getBoolean(key: String, defaultValue: Boolean): Boolean {
return preferenceValuesMap[key] as Boolean? ?: defaultValue
}
override fun contains(s: String): Boolean {
return preferenceValuesMap.containsKey(s)
}
override fun edit(): SharedPreferences.Editor {
return InMemorySharedPreferencesEditor(
removalListener = { key: String ->
preferenceValuesMap.remove(key)
changeListeners.forEach { changeListener -> changeListener.onSharedPreferenceChanged(this, key) }
},
clearListener = {
val copyOfKeysToNotify = preferenceValuesMap.keys.toList()
preferenceValuesMap.clear()
copyOfKeysToNotify.forEach { key ->
changeListeners.forEach { changeListener ->
changeListener.onSharedPreferenceChanged(this, key)
}
}
},
changeListener = { key: String, value: Any? ->
preferenceValuesMap[key] = value
changeListeners.forEach { changeListener -> changeListener.onSharedPreferenceChanged(this, key) }
})
}
override fun registerOnSharedPreferenceChangeListener(listener: SharedPreferences.OnSharedPreferenceChangeListener) {
changeListeners.add(listener)
}
override fun unregisterOnSharedPreferenceChangeListener(listener: SharedPreferences.OnSharedPreferenceChangeListener) {
changeListeners.remove(listener)
}
/**
* Queues up changes, and fires the changeListener after a commit() or apply()
*/
private class InMemorySharedPreferencesEditor(
private val removalListener: (key: String) -> Unit,
private val clearListener: () -> Unit,
private val changeListener: (key: String, value: Any?) -> Unit
) : SharedPreferences.Editor {
private val pendingRemovals = mutableListOf<String>()
private val pendingAdds: HashMap<String, Any?> = HashMap()
private var pendingClear = false
override fun putString(key: String, value: String?): SharedPreferences.Editor {
pendingAdds[key] = value
return this
}
override fun putStringSet(key: String, values: Set<String>?): SharedPreferences.Editor {
pendingAdds[key] = values
return this
}
override fun putInt(key: String, value: Int): SharedPreferences.Editor {
pendingAdds[key] = value
return this
}
override fun putLong(key: String, l: Long): SharedPreferences.Editor {
pendingAdds[key] = l
return this
}
override fun putFloat(key: String, v: Float): SharedPreferences.Editor {
pendingAdds[key] = v
return this
}
override fun putBoolean(key: String, b: Boolean): SharedPreferences.Editor {
pendingAdds[key] = b
return this
}
override fun remove(key: String): SharedPreferences.Editor {
pendingRemovals.add(key)
return this
}
override fun clear(): SharedPreferences.Editor {
pendingClear = true
return this
}
override fun commit(): Boolean {
updatePreferencesWithPendingActions()
return true
}
override fun apply() {
updatePreferencesWithPendingActions()
}
private fun updatePreferencesWithPendingActions() {
// Clear
if (pendingClear) {
clearListener()
}
pendingClear = false // Reset to false
// Removals
pendingRemovals.forEach { key ->
removalListener(key)
}
pendingRemovals.clear()
// Updates
pendingAdds.entries.forEach { entry ->
changeListener(entry.key, entry.value)
}
pendingAdds.clear()
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment