Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android - SharedPreferences - Context

I want to create a helper class for my SharedPreference in android using kotlin. Unfortunately I need the Context and I don't want to set it as parameter everytime I call a preference.

If I use a companion object for the context and set it at application-startup I get the following error: Do not place Android context classes in static fields; this is a memory leak (and also breaks Instant Run)

So how to get the context without passing it everytime I call the preferences?

 var isWorking: Boolean
    get() = getBoolean(IS_WORKING)
    set(isWorking) = setPreference(IS_WORKING, isWorking)

 private fun setPreference(key: String, value: Boolean) {
    val editor = settings.edit()
    editor.putBoolean(key, value)
    editor.commit()
}

 private val settings: SharedPreferences by lazy {
    context.getSharedPreferences("prefs", Context.MODE_PRIVATE)
}
like image 826
Thomas Klammer Avatar asked Dec 07 '22 16:12

Thomas Klammer


1 Answers

Instead of a class, consider using an object. There will be only one instance of it and SharedPreferences can be initialized with application's context, like so:

object AppPreferences {
    private const val NAME = "SpinKotlin"
    private const val MODE = Context.MODE_PRIVATE
    private lateinit var preferences: SharedPreferences
    // list of app specific preferences
    private val IS_FIRST_RUN_PREF = Pair("is_first_run", false)

    fun init(context: Context) {
        preferences = context.getSharedPreferences(NAME, MODE)
    }

    /**
    * SharedPreferences extension function, so we won't need to call edit() 
        and apply()
    * ourselves on every SharedPreferences operation.
    */
    private inline fun SharedPreferences.edit(operation: 
        (SharedPreferences.Editor) -> Unit) {
        val editor = edit()
        operation(editor)
        editor.apply()
    }

    var firstRun: Boolean
        // custom getter to get a preference of a desired type, with a predefined default value
        get() = preferences.getBoolean(IS_FIRST_RUN_PREF.first, IS_FIRST_RUN_PREF.second)

        // custom setter to save a preference back to preferences file
        set(value) = preferences.edit {
            it.putBoolean(IS_FIRST_RUN_PREF.first, value)
        }
}

In Application class:

class SpInKotlinApp : Application() {
    override fun onCreate() {
        super.onCreate()
        AppPreferences.init(this)
    }
}

And because of simplifying reading and writing to properties with custom get() and set() methods, assigning a value is very easy:

if (!AppPreferences.firstRun) {
        AppPreferences.firstRun = true
        Log.d("SpinKotlin", "The value of our pref is: ${AppPreferences.firstRun}")
    }

Check a whole explanation here.

like image 179
lomza Avatar answered Dec 11 '22 11:12

lomza