[Tutorial] How to use SharedPreferences in Kotlin

Android development can be (and usually is) much easier and satisfying with Kotlin, compared to Java. But it’s also quite different. Lots of things, like predefined nullability (or lack of it), no static as we know it, extension and top-level functions are there to be used in our favor. No wonder that it may be confusing what approach to choose, especially when the same thing can be done in different ways.

Today I’m gonna present you a better way of initializing and using SharedPreferences in your Kotlin app. No more repeating code with initialization in every place you want to get a preference, no more long lines to get or set a pref. How to accomplish this? Use object with lateinit and custom getters & setters.

Create a new object called AppPreferences. As objects in Kotlin have, the instance of it will be created on first use and we’ll have only one in our app. So, kind of like a singleton in Java, but without all the worry about thread-safety.

We still need a context to get preferences though, that’s why we can’t initialize it right away. Objects can’t have constructors, so create init() function with a context param.  I have also added an extension function edit(), just to have less of a repeating code. firstRun is an example preference of Boolean type. You can add as many as you wish inside the object. You just override get() and set() methods and, magically, reading and writing is easy like x = false. Great!

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)
        }
}

The preferences itself get initialized in Application’s onCreate() method, which is called only on first app’s run. So, create a new Kotlin class, extend Application and initialize our AppPreferences, like so:

class SpInKotlinApp : Application() {

    override fun onCreate() {
        super.onCreate()
        AppPreferences.init(this)
    }
}

And an example of reading and writing a preference in the main activity:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

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

This is it, really! Very straight-forward usage of preferences in Android. Check the source code on GitHub.

P. S. The code in this post was hugely inspired by savepopulation answer on stackoverflow and Ben Deitch’s blog post, so thank you guys!

Thanks for reading and if you have any suggestions or remarks, just leave a comment below 😉

Like and share:

Published by

Tonia Tkachuk

I'm an Android Developer, writing code for living and for fun. Love beautiful apps with a clean code inside. Enjoy travelling and reading.