russhwolf / multiplatform-settings

A Kotlin Multiplatform library for saving simple key-value data
Apache License 2.0
1.69k stars 67 forks source link

Accessing values using Delegated Properties #61

Closed dbaroncelli closed 4 years ago

dbaroncelli commented 4 years ago

I think I found a clean way to define and access the values, removing a lot of boilerplate code, by using Delegated Properties. In this way, there is no need to specify the key, as it's derived from the property name.

The values can be easily defined in this way, inside an object that implements a base class:

object LocalSettings : SettingsClient() {
    var selectedCountry by StringType("USA")
    var numPassengers by IntType(1)
    var searchesEnabled by BooleanType(false)
}

The base class holds an instance of the MultiplatformSettings, and defines a delegate for each type of values.

open class SettingsClient {

    val settings = Settings()

    inner class StringType(defaultValue : String) {
        val default = defaultValue
        operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
            return settings.getString(property.name, default)
        }
        operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
            settings.putString(property.name, value)
        }
    }

    inner class IntType(defaultValue : Int) {
        val default = defaultValue
        operator fun getValue(thisRef: Any?, property: KProperty<*>): Int {
            return settings.getInt(property.name, default)
        }
        operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) {
            settings.putInt(property.name, value)
        }
    }

    inner class BoolType(defaultValue : Boolean) {
        val default = defaultValue
        operator fun getValue(thisRef: Any?, property: KProperty<*>): Boolean {
            return settings.getBoolean(property.name, default)
        }
        operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Boolean) {
            settings.putBoolean(property.name, value)
        }
    }

}

You might consider of providing a class like SettingsClient in the library, so that people can use the MultiplatformSettings in this very simple way.

russhwolf commented 4 years ago

Delegate APIs already exist. They're implemented as extension functions on Settings, so the library doesn't care about any sort of SettingsClient structure. You can place them wherever makes sense for your application.

val settings: Settings = ...
val a: Int by settings.int("a")
val b: Int by settings.int()
val c: Int? by settings.nullableInt()
dbaroncelli commented 4 years ago

OK, cool! I wasn't aware