|
class MyViewModel(private val sharedPreferences: SharedPreferences) : ViewModel { |
|
var isAdult by sharedPreferences.isAdult |
|
|
|
init { |
|
println(isAdult) // null |
|
isAdult = true |
|
println(isAdult) // true |
|
isAdult.value = false |
|
println(isAdult) // false |
|
|
|
sharedPreferences.isAdultX = true |
|
println(isAdult) // true |
|
} |
|
|
|
} |
|
|
|
class SharedPreferencesX { |
|
companion object { |
|
var SharedPreferences.isAdultX by ofBoolean { PREF_IS_ADULT } // How can we do something like this? |
|
} |
|
} |
|
|
|
val SharedPreferences.isAdult get() = ofBoolean { PREF_IS_ADULT } |
|
|
|
const val PREF_IS_ADULT = "isAdult" |
|
|
|
fun SharedPreferences.ofBoolean( |
|
onKey: () -> String, |
|
): MutableSharedPreferencesState<Boolean?> = BooleanPreference( |
|
onKey = onKey, |
|
sharedPreferences = this, |
|
scope = scope, |
|
) |
|
|
|
class BooleanPreference( |
|
private val sharedPreferences: SharedPreferences, |
|
private val onKey: () -> String, |
|
): MutableSharedPreferencesState<Boolean?> { |
|
override var value: Boolean? |
|
get() = sharedPreferences.getBooleanOrNull(onKey()) |
|
set(value) { |
|
sharedPreferences.edit { putOrNull(onKey(), value) } |
|
} |
|
|
|
override fun component1(): Boolean? = value |
|
|
|
override fun component2(): (Boolean?) -> Unit = { value = it } |
|
} |
|
|
|
|
|
fun SharedPreferences.getBooleanOrNull(key: String) = |
|
if (contains(key)) getBoolean(key, false) else null |
|
|
|
fun SharedPreferences.Editor.putOrNull(key: String, value: Boolean?): SharedPreferences.Editor = |
|
if (value != null) putBoolean(key, value) |
|
else remove(key) |
|
|
|
|
|
interface SharedPreferencesState<T> { |
|
val value: T |
|
} |
|
|
|
interface MutableSharedPreferencesState<T> : SharedPreferencesState<T> { |
|
override var value: T |
|
operator fun component1(): T |
|
operator fun component2(): (T) -> Unit |
|
} |
|
|
|
operator fun <T> SharedPreferencesState<T>.getValue(thisObj: Any?, property: KProperty<*>): T = value |
|
|
|
operator fun <T> MutableSharedPreferencesState<T>.setValue(thisObj: Any?, property: KProperty<*>, value: T) { |
|
this.value = value |
|
} |