Skip to content
This repository was archived by the owner on Nov 14, 2018. It is now read-only.
This repository was archived by the owner on Nov 14, 2018. It is now read-only.

Generic set & get method for SharedPreferences.Editor #435

Open

Description

@pinakinkansara

Is it possible to have generic set & get method for SharedPreferences.Editor?

sharedPreferences.edit {

    putBoolean("key", value)

    putString("key",value)
}

Instead of that can we have some thing like below to set preference.
Idea is to get ride of putBoolean, putString, putLong instead only use set.

prefs.edit{

          set("Test" to "Blame")

          set("Rest" to 12)

          set("Best" to 12.30f)

 }

Similar way for getting preferences instead of getString, getBoolean, getLong we should call something like below.

prefs.get("Test" to null)

Also my proposal is as below.

For setting values in preference.

fun <T: Any>SharedPreferences.Editor.set(pair: Pair<String,T>){

    when(pair.second){
        is String -> putString(pair.first,pair.second as String)
        is Int -> putInt(pair.first,pair.second as Int)
        is Long -> putLong(pair.first,pair.second as Long)
        is Float -> putFloat(pair.first,pair.second as Float)
    }

}

For getting values from preference

fun <T: Any>get(key: String , defaultVal: T?): Serializable? {
        val preference = getSharedPreferences()
        return when(defaultVal){
            is String,null -> preference.getString(key,defaultVal.toString())
            is Int -> preference.getInt(key,defaultVal.toInt())
            is Float -> preference.getFloat(key,defaultVal.toFloat())
            is Long -> preference.getLong(key,defaultVal.toLong())
            else -> IllegalArgumentException("Type mismatch")
        }
    }

Activity

  1. dovahkiin98 commented on Mar 14, 2018

    @dovahkiin98

    Most extensions are inline, also, set would be better if you use a key and a value, looks like an indexer

    prefs["key"] = 5
    prefs["key", 5]
    inline operator fun <reified T> SharedPreferences.Editor.set(key: String, value: T) {
        when (T::class.java) {
            Int::class.java -> putInt(key, value as Int)
            Long::class.java -> putLong(key, value as Long)
        }
    }
    
    inline operator fun <reified T> SharedPreferences.get(key: String, defValue: T): T = when (T::class.java) {
        Int::class.java -> getInt(key, defValue as Int) as T
        Long::class.java -> getLong(key, defValue as Long) as T
        else -> 0 as T
    }
  2. JakeWharton commented on Mar 14, 2018

    @JakeWharton
    Contributor

    I don't think we want to encourage a reduction in type safety inside of a lambda block where we're not forced to. The current preference interaction is fairly concise. I'm not sure what we gain from changing it?

  3. dovahkiin98 commented on Mar 14, 2018

    @dovahkiin98

    We can make getting and setting values easier.
    I would like to use this concept in Intent and Bundle too, makes interacting with values easy and quick

  4. JakeWharton commented on Mar 14, 2018

    @JakeWharton
    Contributor

    It's not any easier, you're just code golfing character count and reducing type safety.

  5. rongi commented on Mar 15, 2018

    @rongi

    It's easier because you no longer need to think which method to use: putString()or putBoolean(), or putInt(). Just use a generic set(), or put(), or whatever, and you are golden.

  6. pinakinkansara commented on Mar 29, 2018

    @pinakinkansara
    Author

    @JakeWharton
    While looking at android-ktx code base, I found out that Bundle
    are also implemented as Feature I demanded for.
    If type safety is the only concern for SharePreference to apply generic set & get method then it should also be concern for Bundle as well.

  7. JakeWharton commented on Mar 29, 2018

    @JakeWharton
    Contributor
  8. AllanWang commented on Jun 22, 2018

    @AllanWang

    In light of a more "generic" get & set, one thing I did was a delegation pattern much like that of the bundle.

    (README and Source)

    The implementation essentially allows us to do something like:

    object MyPrefs : KPref() {
        var textColor: Int by kpref("TEXT_COLOR", Color.WHITE)
        var bgColor: Int by kpref("BG_COLOR", Color.BLACK)
        var isFirstLaunch: Boolean by kpref("IS_FIRST_LAUNCH", true)
        ...
    }

    Where kpref is defined for the supported types and backed by a general class that checks instance types.

    You would then be able to get and set your preferences much as you would get and set a normal variable:

    MyPrefs.textColor = Color.BLACK
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions