Mark
07/08/2020, 5:13 AMclass Settings(val sharedPreferences: SharedPreferences) {
val appVersion: Int by <http://sharedPreferences.int|sharedPreferences.int>(APP_VERSION)
}
but I would like to do:
val Settings.appVersion: Int by <http://sharedPreferences.int|sharedPreferences.int>(APP_VERSION)
Viktor Petrovski
07/08/2020, 5:49 AMval Settings.appVersion(sharedPreferences: SharedPreferences): Int by <http://sharedPreferences.int|sharedPreferences.int>(APP_VERSION)
Adam Powell
07/08/2020, 1:31 PMval Settings.appVersion: Int get() = sharedPreferences.getInt(APP_VERSION, 0)
Mark
07/09/2020, 3:23 AMvar
instead of val
there, but anyway, so as a (somewhat ridiculous and inefficient) workaround you could have:
private class AppVersionValueHolder(sharedPreferences: SharedPreferences) {
var value by <http://sharedPreferences.int|sharedPreferences.int>(APP_VERSION)
}
var Settings.appVersion: Int
get() = AppVersionValueHolder(sharedPreferences).value
set(value) {
AppVersionValueHolder(sharedPreferences).value = value
}
Mark
07/09/2020, 3:43 AMprivate val Settings.appVersionProperty
get() = <http://sharedPreferences.int|sharedPreferences.int>(APP_VERSION)
var Settings.appVersion: Int
get() = appVersionProperty.getValue(Any(), ???)
set(value) {
appVersionProperty.setValue(Any(), ???, value)
But what fake value can be given for the property?
So, better for the int()
extension function to actually return an implementation of something like:
interface GetterSetter<T> {
fun getValue(): T
fun setValue(value: T)
}
and provide an extension function to convert that to a property:
fun <T> GetterSetter<T>.asProperty() = object: ReadWriteProperty<Any, T> {
override fun getValue(thisRef: Any, property: KProperty<*>): T = getValue()
override fun setValue(thisRef: Any, property: KProperty<*>, value: T) = setValue(value)
}
So finally we have both ways available:
private val Settings.appVersionGetterSetter
get() = sharedPreferences.intGetterSetter(APP_VERSION)
var Settings.appVersion: Int
get() = appVersionGetterSetter.getValue()
set(value) {
appVersionGetterSetter.setValue(value)
}
class Settings(val sharedPreferences: SharedPreferences) {
var somethingElse by sharedPreferences.intGetterSetter(SOMETHING_ELSE).asProperty()
}
Of course, this wouldn’t make any sense if the getter and setter is just doing simple getInt
, putInt
calls, but might be useful if there are some sanity checks and/or exception handling going on.Tobias Berger
07/09/2020, 2:45 PMTobias Berger
07/09/2020, 2:57 PMthisRef
parameter in its get/setValue functions.Mark
07/10/2020, 6:59 AMthisRef
makes so much more sense. My GetterSetter
now becomes:
interface PreferencesGetterSetter<T> {
fun SharedPreferences.getValue(): T
fun SharedPreferences.Editor.setValue(value: T): Boolean
}
and can be converted to a property in a similar way as before:
fun <T> PreferencesGetterSetter<T>.asProperty() = object : ReadWriteProperty<SharedPreferences, T> {
override fun getValue(thisRef: SharedPreferences, property: KProperty<*>): T = thisRef.getValue()
override fun setValue(thisRef: SharedPreferences, property: KProperty<*>, value: T) =
thisRef.edit { setValue(value) }
}
which will work for concrete properties of any class implementing SharedPreferences
. For classes that don’t we have:
fun <T> ReadWriteProperty<SharedPreferences, T>.of(
sharedPreferences: SharedPreferences
): ReadWriteProperty<Any, T> {
return object : ReadWriteProperty<Any, T> {
override fun getValue(thisRef: Any, property: KProperty<*>): T {
return this@of.getValue(sharedPreferences, property)
}
override fun setValue(thisRef: Any, property: KProperty<*>, value: T) {
this@of.setValue(sharedPreferences, property, value)
}
}
}
and finally for extension properties we can use:
fun <R, T> ReadWriteProperty<SharedPreferences, T>.of(sharedPreferencesLambda: R.() -> SharedPreferences) =
object : ReadWriteProperty<R, T> {
override fun getValue(thisRef: R, property: KProperty<*>): T {
return this@of.getValue(thisRef.sharedPreferencesLambda(), property)
}
override fun setValue(thisRef: R, property: KProperty<*>, value: T) {
this@of.setValue(thisRef.sharedPreferencesLambda(), property, value)
}
}
So now we have:
var Settings.appVersion by int(APP_VERSION).of { sharedPreferences }
class Settings(val sharedPreferences: SharedPreferences) {
var somethingElse by int(SOMETHING_ELSE).of { sharedPreferences }
}
See here for more: https://gist.github.com/marcardar/18ca4f53deb9f451cd431e3979fb59a5Mark
07/11/2020, 3:51 AMclass MySettings1(): SharedPreferences {
var myInt1 by int("myPrefKey1")
...
}
var MySettings1.myInt1Ext2 by <http://PreferencesGetterSetter.int|PreferencesGetterSetter.int>("myPrefKey1Ext2").asProperty()
class MySettings2(private val sharedPreferences: SharedPreferences) {
var myInt2 by <http://sharedPreferences.int|sharedPreferences.int>("myPrefKey2")
}
class MySettings3(val sharedPreferences: SharedPreferences) {
var myInt3 by <http://sharedPreferences.int|sharedPreferences.int>("myPrefKey3")
}
class MyClassUsingSettings3() {
val mySettings3: MySettings3 ...
var myInt3Outside = <http://mySettings3.sharedPreferences.int|mySettings3.sharedPreferences.int>("myPrefKey3Outside")
}
var MySettings3.myInt3Ext by <http://PreferencesGetterSetter.int|PreferencesGetterSetter.int>("myPrefKey3Ext").asProperty { sharedPreferences }
class MySettings4(private val sharedPreferences: SharedPreferences) {
var myInt4 by int("myPrefKey4")
// so that other classes can declare properties using the underlying sharedPreferences
// and extension functions can declare properties on this class using the underlying sharedPreferences
companion object: SharedPreferencesProperties<MySettings4>( { sharedPreferences } )
}
class MyClassUsingSettings4() {
val mySettings4 = MySettings4(...)
var myInt4Other by MySettings4.of(mySettings4).int("myPrefKey4Other")
}
var MySettings4.myInt4Ext by <http://MySettings4.int|MySettings4.int>("myPrefKey4Ext")
https://gist.github.com/marcardar/2ea4b83b261abf58cdfc8e79b030c5feMark
07/11/2020, 3:58 AMvar Settings.appVersion by <http://Settings.int|Settings.int>(APP_VERSION)
class Settings(private val sharedPreferences: SharedPreferences) {
var somethingElse by int(SOMETHING_ELSE)
companion object : SharedPreferencesProperties<Settings>({ sharedPrefs })
}