Skip to content

Instantly share code, notes, and snippets.

@benigumocom
Forked from wispborne/Preferences.kt
Created January 14, 2021 03:02

Revisions

  1. @wispborne wispborne revised this gist Oct 25, 2018. 1 changed file with 67 additions and 69 deletions.
    136 changes: 67 additions & 69 deletions Preferences.kt
    Original file line number Diff line number Diff line change
    @@ -14,6 +14,9 @@ import kotlin.reflect.KProperty
    * }
    * ```
    */
    // Ignore unused warning. This class needs to handle all data types, regardless of whether the method is used.
    // Allow unchecked casts - we can blindly trust that data we read is the same type we saved it as..
    @Suppress("UNCHECKED_CAST", "unused")
    abstract class Preferences(private var context: Context, private val name: String? = null) {
    private val prefs: SharedPreferences by lazy {
    context.getSharedPreferences(name ?: javaClass.simpleName, Context.MODE_PRIVATE)
    @@ -22,7 +25,6 @@ abstract class Preferences(private var context: Context, private val name: Strin
    private val listeners = mutableListOf<SharedPrefsListener>()

    abstract class PrefDelegate<T>(val prefKey: String?) {

    abstract operator fun getValue(thisRef: Any?, property: KProperty<*>): T
    abstract operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T)
    }
    @@ -41,85 +43,81 @@ abstract class Preferences(private var context: Context, private val name: Strin

    fun clearListeners() = listeners.clear()

    fun stringPref(prefKey: String? = null, defaultValue: String? = null) = StringPrefDelegate(prefKey, defaultValue)

    inner class StringPrefDelegate(prefKey: String? = null, val defaultValue: String?) :
    PrefDelegate<String?>(prefKey) {
    override fun getValue(thisRef: Any?, property: KProperty<*>): String? =
    prefs.getString(prefKey ?: property.name, defaultValue)

    override fun setValue(thisRef: Any?, property: KProperty<*>, value: String?) {
    prefs.edit().putString(prefKey ?: property.name, value).apply()
    onPrefChanged(property)
    }
    enum class StorableType {
    String,
    Int,
    Float,
    Boolean,
    Long,
    StringSet
    }

    fun intPref(prefKey: String? = null, defaultValue: Int = 0) = IntPrefDelegate(prefKey, defaultValue)

    inner class IntPrefDelegate(prefKey: String? = null, val defaultValue: Int) : PrefDelegate<Int>(prefKey) {
    override fun getValue(thisRef: Any?, property: KProperty<*>) =
    prefs.getInt(prefKey ?: property.name, defaultValue)

    override fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) {
    prefs.edit().putInt(prefKey ?: property.name, value).apply()
    onPrefChanged(property)
    inner class GenericPrefDelegate<T>(prefKey: String? = null, private val defaultValue: T?, val type: StorableType) :
    PrefDelegate<T?>(prefKey) {
    override fun getValue(thisRef: Any?, property: KProperty<*>): T? =
    when (type) {
    StorableType.String ->
    prefs.getString(prefKey ?: property.name, defaultValue as String?) as T?
    StorableType.Int ->
    prefs.getInt(prefKey ?: property.name, defaultValue as Int) as T?
    StorableType.Float ->
    prefs.getFloat(prefKey ?: property.name, defaultValue as Float) as T?
    StorableType.Boolean ->
    prefs.getBoolean(prefKey ?: property.name, defaultValue as Boolean) as T?
    StorableType.Long ->
    prefs.getLong(prefKey ?: property.name, defaultValue as Long) as T?
    StorableType.StringSet ->
    prefs.getStringSet(prefKey ?: property.name, defaultValue as Set<String>) as T?
    }

    override fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) {
    when (type) {
    StorableType.String -> {
    prefs.edit().putString(prefKey ?: property.name, value as String?).apply()
    onPrefChanged(property)
    }
    StorableType.Int -> {
    prefs.edit().putInt(prefKey ?: property.name, value as Int).apply()
    onPrefChanged(property)
    }
    StorableType.Float -> {
    prefs.edit().putFloat(prefKey ?: property.name, value as Float).apply()
    onPrefChanged(property)
    }
    StorableType.Boolean -> {
    prefs.edit().putBoolean(prefKey ?: property.name, value as Boolean).apply()
    onPrefChanged(property)
    }
    StorableType.Long -> {
    prefs.edit().putLong(prefKey ?: property.name, value as Long).apply()
    onPrefChanged(property)
    }
    StorableType.StringSet -> {
    prefs.edit().putStringSet(prefKey ?: property.name, value as Set<String>).apply()
    onPrefChanged(property)
    }
    }
    }
    }


    fun floatPref(prefKey: String? = null, defaultValue: Float = 0f) = FloatPrefDelegate(prefKey, defaultValue)

    inner class FloatPrefDelegate(prefKey: String? = null, val defaultValue: Float) : PrefDelegate<Float>(prefKey) {
    override fun getValue(thisRef: Any?, property: KProperty<*>) =
    prefs.getFloat(prefKey ?: property.name, defaultValue)

    override fun setValue(thisRef: Any?, property: KProperty<*>, value: Float) {
    prefs.edit().putFloat(prefKey ?: property.name, value).apply()
    onPrefChanged(property)
    }
    }

    fun stringPref(prefKey: String? = null, defaultValue: String? = null) =
    GenericPrefDelegate(prefKey, defaultValue, StorableType.String)

    fun booleanPref(prefKey: String? = null, defaultValue: Boolean = false) = BooleanPrefDelegate(prefKey, defaultValue)
    fun intPref(prefKey: String? = null, defaultValue: Int = 0) =
    GenericPrefDelegate(prefKey, defaultValue, StorableType.Int)

    inner class BooleanPrefDelegate(prefKey: String? = null, val defaultValue: Boolean) :
    PrefDelegate<Boolean>(prefKey) {
    override fun getValue(thisRef: Any?, property: KProperty<*>) =
    prefs.getBoolean(prefKey ?: property.name, defaultValue)
    fun floatPref(prefKey: String? = null, defaultValue: Float = 0f) =
    GenericPrefDelegate(prefKey, defaultValue, StorableType.Float)

    override fun setValue(thisRef: Any?, property: KProperty<*>, value: Boolean) {
    prefs.edit().putBoolean(prefKey ?: property.name, value).apply()
    onPrefChanged(property)
    }
    }


    fun longPref(prefKey: String? = null, defaultValue: Long = 0L) = LongPrefDelegate(prefKey, defaultValue)
    fun booleanPref(prefKey: String? = null, defaultValue: Boolean = false) =
    GenericPrefDelegate(prefKey, defaultValue, StorableType.Boolean)

    inner class LongPrefDelegate(prefKey: String? = null, val defaultValue: Long) : PrefDelegate<Long>(prefKey) {
    override fun getValue(thisRef: Any?, property: KProperty<*>) =
    prefs.getLong(prefKey ?: property.name, defaultValue)

    override fun setValue(thisRef: Any?, property: KProperty<*>, value: Long) {
    prefs.edit().putLong(prefKey ?: property.name, value).apply()
    onPrefChanged(property)
    }
    }
    fun longPref(prefKey: String? = null, defaultValue: Long = 0L) =
    GenericPrefDelegate(prefKey, defaultValue, StorableType.Long)


    fun stringSetPref(prefKey: String? = null, defaultValue: Set<String> = HashSet<String>()) =
    StringSetPrefDelegate(prefKey, defaultValue)

    inner class StringSetPrefDelegate(prefKey: String? = null, val defaultValue: Set<String>) :
    PrefDelegate<Set<String>>(prefKey) {
    override fun getValue(thisRef: Any?, property: KProperty<*>): Set<String> =
    prefs.getStringSet(prefKey ?: property.name, defaultValue)

    override fun setValue(thisRef: Any?, property: KProperty<*>, value: Set<String>) {
    prefs.edit().putStringSet(prefKey ?: property.name, value).apply()
    onPrefChanged(property)
    }
    }
    fun stringSetPref(prefKey: String? = null, defaultValue: Set<String> = HashSet()) =
    GenericPrefDelegate(prefKey, defaultValue, StorableType.StringSet)

    private fun onPrefChanged(property: KProperty<*>) {
    listeners.forEach { it.onSharedPrefChanged(property) }
  2. @wispborne wispborne revised this gist Sep 14, 2018. 2 changed files with 28 additions and 34 deletions.
    60 changes: 28 additions & 32 deletions Preferences.kt
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,3 @@

    import android.content.Context
    import android.content.SharedPreferences
    import kotlin.reflect.KProperty
    @@ -8,41 +7,22 @@ import kotlin.reflect.KProperty
    *
    * Usage:
    *
    * `Preferences.init(context)`
    *
    * ```kotlin
    * class UserPreferences : Preferences() {
    * var emailAccount by stringPref()
    * var showSystemAppsPreference by booleanPref()
    * }
    * ```
    */
    abstract class Preferences {
    companion object {
    private var context: Context? = null

    /**
    * Initialize PrefDelegate with a Context reference.
    *
    * **This method needs to be called before any other usage of PrefDelegate!!**
    */
    fun init(context: Context) {
    this.context = context
    }
    }

    abstract class Preferences(private var context: Context, private val name: String? = null) {
    private val prefs: SharedPreferences by lazy {
    if (context != null)
    context!!.getSharedPreferences(javaClass.simpleName, Context.MODE_PRIVATE)
    else
    throw IllegalStateException("Context was not initialized. Call Preferences.init(context) before using it")
    context.getSharedPreferences(name ?: javaClass.simpleName, Context.MODE_PRIVATE)
    }

    private val listeners = mutableListOf<SharedPrefsListener>()

    abstract class PrefDelegate<T>(val prefKey: String?) {


    abstract operator fun getValue(thisRef: Any?, property: KProperty<*>): T
    abstract operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T)
    }
    @@ -63,8 +43,11 @@ abstract class Preferences {

    fun stringPref(prefKey: String? = null, defaultValue: String? = null) = StringPrefDelegate(prefKey, defaultValue)

    inner class StringPrefDelegate(prefKey: String? = null, val defaultValue: String?) : PrefDelegate<String?>(prefKey) {
    override fun getValue(thisRef: Any?, property: KProperty<*>): String? = prefs.getString(prefKey ?: property.name, defaultValue)
    inner class StringPrefDelegate(prefKey: String? = null, val defaultValue: String?) :
    PrefDelegate<String?>(prefKey) {
    override fun getValue(thisRef: Any?, property: KProperty<*>): String? =
    prefs.getString(prefKey ?: property.name, defaultValue)

    override fun setValue(thisRef: Any?, property: KProperty<*>, value: String?) {
    prefs.edit().putString(prefKey ?: property.name, value).apply()
    onPrefChanged(property)
    @@ -74,7 +57,9 @@ abstract class Preferences {
    fun intPref(prefKey: String? = null, defaultValue: Int = 0) = IntPrefDelegate(prefKey, defaultValue)

    inner class IntPrefDelegate(prefKey: String? = null, val defaultValue: Int) : PrefDelegate<Int>(prefKey) {
    override fun getValue(thisRef: Any?, property: KProperty<*>) = prefs.getInt(prefKey ?: property.name, defaultValue)
    override fun getValue(thisRef: Any?, property: KProperty<*>) =
    prefs.getInt(prefKey ?: property.name, defaultValue)

    override fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) {
    prefs.edit().putInt(prefKey ?: property.name, value).apply()
    onPrefChanged(property)
    @@ -85,7 +70,9 @@ abstract class Preferences {
    fun floatPref(prefKey: String? = null, defaultValue: Float = 0f) = FloatPrefDelegate(prefKey, defaultValue)

    inner class FloatPrefDelegate(prefKey: String? = null, val defaultValue: Float) : PrefDelegate<Float>(prefKey) {
    override fun getValue(thisRef: Any?, property: KProperty<*>) = prefs.getFloat(prefKey ?: property.name, defaultValue)
    override fun getValue(thisRef: Any?, property: KProperty<*>) =
    prefs.getFloat(prefKey ?: property.name, defaultValue)

    override fun setValue(thisRef: Any?, property: KProperty<*>, value: Float) {
    prefs.edit().putFloat(prefKey ?: property.name, value).apply()
    onPrefChanged(property)
    @@ -95,8 +82,11 @@ abstract class Preferences {

    fun booleanPref(prefKey: String? = null, defaultValue: Boolean = false) = BooleanPrefDelegate(prefKey, defaultValue)

    inner class BooleanPrefDelegate(prefKey: String? = null, val defaultValue: Boolean) : PrefDelegate<Boolean>(prefKey) {
    override fun getValue(thisRef: Any?, property: KProperty<*>) = prefs.getBoolean(prefKey ?: property.name, defaultValue)
    inner class BooleanPrefDelegate(prefKey: String? = null, val defaultValue: Boolean) :
    PrefDelegate<Boolean>(prefKey) {
    override fun getValue(thisRef: Any?, property: KProperty<*>) =
    prefs.getBoolean(prefKey ?: property.name, defaultValue)

    override fun setValue(thisRef: Any?, property: KProperty<*>, value: Boolean) {
    prefs.edit().putBoolean(prefKey ?: property.name, value).apply()
    onPrefChanged(property)
    @@ -107,18 +97,24 @@ abstract class Preferences {
    fun longPref(prefKey: String? = null, defaultValue: Long = 0L) = LongPrefDelegate(prefKey, defaultValue)

    inner class LongPrefDelegate(prefKey: String? = null, val defaultValue: Long) : PrefDelegate<Long>(prefKey) {
    override fun getValue(thisRef: Any?, property: KProperty<*>) = prefs.getLong(prefKey ?: property.name, defaultValue)
    override fun getValue(thisRef: Any?, property: KProperty<*>) =
    prefs.getLong(prefKey ?: property.name, defaultValue)

    override fun setValue(thisRef: Any?, property: KProperty<*>, value: Long) {
    prefs.edit().putLong(prefKey ?: property.name, value).apply()
    onPrefChanged(property)
    }
    }


    fun stringSetPref(prefKey: String? = null, defaultValue: Set<String> = HashSet<String>()) = StringSetPrefDelegate(prefKey, defaultValue)
    fun stringSetPref(prefKey: String? = null, defaultValue: Set<String> = HashSet<String>()) =
    StringSetPrefDelegate(prefKey, defaultValue)

    inner class StringSetPrefDelegate(prefKey: String? = null, val defaultValue: Set<String>) :
    PrefDelegate<Set<String>>(prefKey) {
    override fun getValue(thisRef: Any?, property: KProperty<*>): Set<String> =
    prefs.getStringSet(prefKey ?: property.name, defaultValue)

    inner class StringSetPrefDelegate(prefKey: String? = null, val defaultValue: Set<String>) : PrefDelegate<Set<String>>(prefKey) {
    override fun getValue(thisRef: Any?, property: KProperty<*>): Set<String> = prefs.getStringSet(prefKey ?: property.name, defaultValue)
    override fun setValue(thisRef: Any?, property: KProperty<*>, value: Set<String>) {
    prefs.edit().putStringSet(prefKey ?: property.name, value).apply()
    onPrefChanged(property)
    2 changes: 0 additions & 2 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -2,8 +2,6 @@

    Wrapper class for `SharedPreferences`, leveraging the awesome delegate syntax in Kotlin.

    Call `Preferences.init(context)` in your `Application` class.

    Example preferences definition:

    ```kotlin
  3. @wispborne wispborne revised this gist May 9, 2017. 1 changed file with 32 additions and 0 deletions.
    32 changes: 32 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,32 @@
    # Usage

    Wrapper class for `SharedPreferences`, leveraging the awesome delegate syntax in Kotlin.

    Call `Preferences.init(context)` in your `Application` class.

    Example preferences definition:

    ```kotlin
    class UserPreferences : Preferences() {
    var emailAccount by stringPref()
    var allowAnonymousLogging by booleanPref()
    }
    ```

    Example usage:

    ```kotlin
    preferences.allowAnonymousLogging = false
    ```

    Example listener (not exactly the cleanest-looking but it works):

    ```kotlin
    preferences.addListener(object : Preferences.SharedPrefsListener {
    override fun onSharedPrefChanged(property: KProperty<*>) {
    if (UserPreferences::allowAnonymousLogging.name == property.name) {
    initLogging()
    }
    }
    })
    ```
  4. @wispborne wispborne revised this gist May 5, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Preferences.kt
    Original file line number Diff line number Diff line change
    @@ -64,7 +64,7 @@ abstract class Preferences {
    fun stringPref(prefKey: String? = null, defaultValue: String? = null) = StringPrefDelegate(prefKey, defaultValue)

    inner class StringPrefDelegate(prefKey: String? = null, val defaultValue: String?) : PrefDelegate<String?>(prefKey) {
    override fun getValue(thisRef: Any?, property: KProperty<*>): String = prefs.getString(prefKey ?: property.name, defaultValue)
    override fun getValue(thisRef: Any?, property: KProperty<*>): String? = prefs.getString(prefKey ?: property.name, defaultValue)
    override fun setValue(thisRef: Any?, property: KProperty<*>, value: String?) {
    prefs.edit().putString(prefKey ?: property.name, value).apply()
    onPrefChanged(property)
  5. @wispborne wispborne created this gist May 5, 2017.
    131 changes: 131 additions & 0 deletions Preferences.kt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,131 @@

    import android.content.Context
    import android.content.SharedPreferences
    import kotlin.reflect.KProperty

    /**
    * Represents a single [SharedPreferences] file.
    *
    * Usage:
    *
    * `Preferences.init(context)`
    *
    * ```kotlin
    * class UserPreferences : Preferences() {
    * var emailAccount by stringPref()
    * var showSystemAppsPreference by booleanPref()
    * }
    * ```
    */
    abstract class Preferences {
    companion object {
    private var context: Context? = null

    /**
    * Initialize PrefDelegate with a Context reference.
    *
    * **This method needs to be called before any other usage of PrefDelegate!!**
    */
    fun init(context: Context) {
    this.context = context
    }
    }

    private val prefs: SharedPreferences by lazy {
    if (context != null)
    context!!.getSharedPreferences(javaClass.simpleName, Context.MODE_PRIVATE)
    else
    throw IllegalStateException("Context was not initialized. Call Preferences.init(context) before using it")
    }

    private val listeners = mutableListOf<SharedPrefsListener>()

    abstract class PrefDelegate<T>(val prefKey: String?) {


    abstract operator fun getValue(thisRef: Any?, property: KProperty<*>): T
    abstract operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T)
    }

    interface SharedPrefsListener {
    fun onSharedPrefChanged(property: KProperty<*>)
    }

    fun addListener(sharedPrefsListener: SharedPrefsListener) {
    listeners.add(sharedPrefsListener)
    }

    fun removeListener(sharedPrefsListener: SharedPrefsListener) {
    listeners.remove(sharedPrefsListener)
    }

    fun clearListeners() = listeners.clear()

    fun stringPref(prefKey: String? = null, defaultValue: String? = null) = StringPrefDelegate(prefKey, defaultValue)

    inner class StringPrefDelegate(prefKey: String? = null, val defaultValue: String?) : PrefDelegate<String?>(prefKey) {
    override fun getValue(thisRef: Any?, property: KProperty<*>): String = prefs.getString(prefKey ?: property.name, defaultValue)
    override fun setValue(thisRef: Any?, property: KProperty<*>, value: String?) {
    prefs.edit().putString(prefKey ?: property.name, value).apply()
    onPrefChanged(property)
    }
    }

    fun intPref(prefKey: String? = null, defaultValue: Int = 0) = IntPrefDelegate(prefKey, defaultValue)

    inner class IntPrefDelegate(prefKey: String? = null, val defaultValue: Int) : PrefDelegate<Int>(prefKey) {
    override fun getValue(thisRef: Any?, property: KProperty<*>) = prefs.getInt(prefKey ?: property.name, defaultValue)
    override fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) {
    prefs.edit().putInt(prefKey ?: property.name, value).apply()
    onPrefChanged(property)
    }
    }


    fun floatPref(prefKey: String? = null, defaultValue: Float = 0f) = FloatPrefDelegate(prefKey, defaultValue)

    inner class FloatPrefDelegate(prefKey: String? = null, val defaultValue: Float) : PrefDelegate<Float>(prefKey) {
    override fun getValue(thisRef: Any?, property: KProperty<*>) = prefs.getFloat(prefKey ?: property.name, defaultValue)
    override fun setValue(thisRef: Any?, property: KProperty<*>, value: Float) {
    prefs.edit().putFloat(prefKey ?: property.name, value).apply()
    onPrefChanged(property)
    }
    }


    fun booleanPref(prefKey: String? = null, defaultValue: Boolean = false) = BooleanPrefDelegate(prefKey, defaultValue)

    inner class BooleanPrefDelegate(prefKey: String? = null, val defaultValue: Boolean) : PrefDelegate<Boolean>(prefKey) {
    override fun getValue(thisRef: Any?, property: KProperty<*>) = prefs.getBoolean(prefKey ?: property.name, defaultValue)
    override fun setValue(thisRef: Any?, property: KProperty<*>, value: Boolean) {
    prefs.edit().putBoolean(prefKey ?: property.name, value).apply()
    onPrefChanged(property)
    }
    }


    fun longPref(prefKey: String? = null, defaultValue: Long = 0L) = LongPrefDelegate(prefKey, defaultValue)

    inner class LongPrefDelegate(prefKey: String? = null, val defaultValue: Long) : PrefDelegate<Long>(prefKey) {
    override fun getValue(thisRef: Any?, property: KProperty<*>) = prefs.getLong(prefKey ?: property.name, defaultValue)
    override fun setValue(thisRef: Any?, property: KProperty<*>, value: Long) {
    prefs.edit().putLong(prefKey ?: property.name, value).apply()
    onPrefChanged(property)
    }
    }


    fun stringSetPref(prefKey: String? = null, defaultValue: Set<String> = HashSet<String>()) = StringSetPrefDelegate(prefKey, defaultValue)

    inner class StringSetPrefDelegate(prefKey: String? = null, val defaultValue: Set<String>) : PrefDelegate<Set<String>>(prefKey) {
    override fun getValue(thisRef: Any?, property: KProperty<*>): Set<String> = prefs.getStringSet(prefKey ?: property.name, defaultValue)
    override fun setValue(thisRef: Any?, property: KProperty<*>, value: Set<String>) {
    prefs.edit().putStringSet(prefKey ?: property.name, value).apply()
    onPrefChanged(property)
    }
    }

    private fun onPrefChanged(property: KProperty<*>) {
    listeners.forEach { it.onSharedPrefChanged(property) }
    }
    }