In this tutorial, we’ll learn how to implement SharedPreferences in our Android Application using Kotlin.
SharedPreferences is part of the Android API since API level 1. It’s an interface that allows us to store/modify/delete data locally.
Generally, it is used to cache user local data such as login forms. The data is stored in the form of a key-value pair.
You can create multiple files to hold the SharedPreferences data.
Let’s look at some important methods for SharedPreferences.
getSharedPreferences(String, int)
method is used to retrieve an instance of theSharedPreferences
.
HereString
is the name of the SharedPreferences file andint
is the Context passed.- The
SharedPreferences.Editor()
is used to edit values in theSharedPreferences
. - We can call
commit()
orapply()
to save the values in the SharedPreferences file. Thecommit()
saves the values immediately whereasapply()
saves the values asynchronously.
We can set values on our SharedPreference instance using Kotlin in the following way.
1 2 3 4 5 6 |
val sharedPreference = getSharedPreferences("PREFERENCE_NAME",Context.MODE_PRIVATE) var editor = sharedPreference.edit() editor.putString("username","Anupam") editor.putLong("l",100L) editor.commit() |
For retrieving a value:
1 2 3 |
sharedPreference.getString("username","defaultName") sharedPreference.getLong("l",1L) |
The permitted types on a SharedPreference instance are:
We can also clear all the values or remove a particular value by calling clear()
and remove(String key)
methods.
1 2 3 |
editor.clear() editor.remove("username") |
Note: Changes made to the editor after the commit or apply aren’t considered.
The above way to save and retrieve values from a SharedPreference is nearly the same as we do in Java.
So where’s the magic of Kotlin?
That’s what we’ll see next through an example android application.
In this application, we’ll have a login screen, which allows us to save/clear the form data.
1. Layout code
The code for the activity_main.xml
layout file is given below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <EditText android:id="@+id/inUserId" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:hint="User ID" android:inputType="number" /> <EditText android:id="@+id/inPassword" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/inUserId" android:hint="Password" android:inputType="textPassword" /> <Button android:id="@+id/btnSave" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/inPassword" android:text="SAVE USER DATA" /> <Button android:id="@+id/btnClear" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_below="@+id/btnSave" android:text="CLEAR USER DATA" /> <Button android:id="@+id/btnShow" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_below="@+id/inPassword" android:text="SHOW" /> <Button android:id="@+id/btnShowDefault" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:layout_alignParentRight="true" android:layout_below="@+id/btnSave" android:text="Show Default" /> </RelativeLayout> |
2. MainActivity Kotlin Code
The code for the MainActivity.kt
Kotlin class is given below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
package com.journaldev.androidlysharedpreferences import android.content.Context import android.content.SharedPreferences import android.support.v7.app.AppCompatActivity import android.os.Bundle import android.preference.PreferenceManager import android.view.View import com.journaldev.androidlysharedpreferences.PreferenceHelper.defaultPreference import com.journaldev.androidlysharedpreferences.PreferenceHelper.password import com.journaldev.androidlysharedpreferences.PreferenceHelper.userId import com.journaldev.androidlysharedpreferences.PreferenceHelper.clearValues import com.journaldev.androidlysharedpreferences.PreferenceHelper.customPreference import kotlinx.android.synthetic.main.activity_main.* class MainActivity : AppCompatActivity(), View.OnClickListener { val CUSTOM_PREF_NAME = "User_data" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) btnSave.setOnClickListener(this) btnClear.setOnClickListener(this) btnShow.setOnClickListener(this) btnShowDefault.setOnClickListener(this) } override fun onClick(v: View?) { val prefs = customPreference(this, CUSTOM_PREF_NAME) when (v?.id) { R.id.btnSave -> { prefs.password = inPassword.text.toString() prefs.userId = inUserId.text.toString().toInt() } R.id.btnClear -> { prefs.clearValues } R.id.btnShow -> { inUserId.setText(prefs.userId.toString()) inPassword.setText(prefs.password) } R.id.btnShowDefault -> { val defaultPrefs = defaultPreference(this) inUserId.setText(defaultPrefs.userId.toString()) inPassword.setText(defaultPrefs.password) } } } } object PreferenceHelper { val USER_ID = "USER_ID" val USER_PASSWORD = "PASSWORD" fun defaultPreference(context: Context): SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) fun customPreference(context: Context, name: String): SharedPreferences = context.getSharedPreferences(name, Context.MODE_PRIVATE) inline fun SharedPreferences.editMe(operation: (SharedPreferences.Editor) -> Unit) { val editMe = edit() operation(editMe) editMe.apply() } var SharedPreferences.userId get() = getInt(USER_ID, 0) set(value) { editMe { it.putInt(USER_ID, value) } } var SharedPreferences.password get() = getString(USER_PASSWORD, "") set(value) { editMe { it.putString(USER_PASSWORD, value) } } var SharedPreferences.clearValues get() = { } set(value) { editMe { it.clear() } } } |
Thanks to Kotlin Android Extensions, we don’t have to use findViewById for each XML view.
In the above code, we are creating a singleton class using the object
keyword.
We are declaring an inline higher-order function named editMe(), which holds the logic for the edit operation.
We’ve created separate properties for each of the values. We are using the get and set Kotlin properties to retrieve and set the data in the shared preferences.
Kotlin has reduced the code verbosity and it looks much cleaner.
Furthermore, we can make it more concise by using another Kotlin higher-order function shown below.
1 2 3 4 5 6 7 8 9 10 11 12 |
fun SharedPreferences.Editor.put(pair: Pair<String, Any>) { val key = pair.first val value = pair.second when(value) { is String -> putString(key, value) is Int -> putInt(key, value) is Boolean -> putBoolean(key, value) is Long -> putLong(key, value) is Float -> putFloat(key, value) else -> error("Only primitive types can be stored in SharedPreferences") } |
And we do the following while setting the values:
1 2 3 4 5 6 7 8 |
var SharedPreferences.password get() = getString(USER_PASSWORD, "") set(value) { editMe { it.put(USER_PASSWORD to value) } } |
This is as close as Kotlin can get you to the English Language.
The output of the above application in action is given below.