Open In App

Preferences DataStore in Android

Improve
Improve
Like Article
Like
Save
Share
Report

Preference Data Store is used to store data permanently in android. Earlier we had to Shared Preferences for the same but since it is deprecated we are using Data Store now. A sample video is given below to get an idea about what we are going to do in this article. Note that we are going to implement this project using the Kotlin language.

Step by Step Implementation

Step 1: Create a new project

To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio. Note that select Kotlin as the programming language

Step 2: Add dependency inside build.gradle(app)

Add the Data Store, Lifecycle, and Coroutines dependency inside the build.gradle(app) and click on the sync now button.

   // Preferences DataStore

   implementation “androidx.datastore:datastore-preferences:1.0.0-alpha01”

   // Lifecycle components

   implementation “androidx.lifecycle:lifecycle-livedata-ktx:2.2.0”

   implementation “androidx.lifecycle:lifecycle-extensions:2.2.0”

   implementation “androidx.lifecycle:lifecycle-common-java8:2.2.0”

   implementation “androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0”

   // Kotlin coroutines components

   implementation “org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.10”

   api “org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.1”

   api “org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1”

Step 3: Working with the activity_main.xml file

Go to the activity_main.xml file and refer to the following code. Below is the code for the activity_main.xml file. This is for the basic layout used in the app.

XML




<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:orientation="vertical"
    tools:context=".MainActivity">
  
    <EditText
        android:id="@+id/et_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:layout_marginTop="20dp"
        android:ems="10"
        android:hint="Name" />
  
    <EditText
        android:id="@+id/et_age"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:ems="10"
        android:hint="Age"
        android:inputType="number" />
  
    <Button
        android:id="@+id/btn_save"
        android:layout_width="150dp"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:background="#FF7043"
        android:padding="10dp"
        android:text="Save user"
        android:textColor="@android:color/white" />
  
    <TextView
        android:id="@+id/tv_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:text="Name"
        android:textColor="@android:color/black"
        android:textSize="20sp" />
  
    <TextView
        android:id="@+id/tv_age"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:text="Age"
        android:textColor="@android:color/black"
        android:textSize="20sp" />
  
</LinearLayout>


Step 4: Working with the UserManager.kt class

Create a new kotlin class and name it UserManager, this class holds the code for saving and retrieving data from the preference Data Store. Comments are added inside the code to understand the code in more detail.

Kotlin




import android.content.Context
import androidx.datastore.preferences.createDataStore
import androidx.datastore.preferences.edit
import androidx.datastore.preferences.preferencesKey
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
  
class UserManager(context: Context) {
  
    // Create the dataStore and give it a name same as shared preferences
    private val dataStore = context.createDataStore(name = "user_prefs")
  
    // Create some keys we will use them to store and retrieve the data
    companion object {
        val USER_AGE_KEY = preferencesKey<Int>("USER_AGE")
        val USER_NAME_KEY = preferencesKey<String>("USER_NAME")
    }
  
    // Store user data
    // refer to the data store and using edit 
    // we can store values using the keys
    suspend fun storeUser(age: Int, name: String) {
        dataStore.edit {
            it[USER_AGE_KEY] = age
            it[USER_NAME_KEY] = name
  
            // here it refers to the preferences we are editing
  
        }
    }
  
    // Create an age flow to retrieve age from the preferences
    // flow comes from the kotlin coroutine
    val userAgeFlow: Flow<Int> = dataStore.data.map {
        it[USER_AGE_KEY] ?: 0
    }
  
    // Create a name flow to retrieve name from the preferences
    val userNameFlow: Flow<String> = dataStore.data.map {
        it[USER_NAME_KEY] ?: ""
    }
}


Step 5: Working with the MainActivity.kt file

Go to the MainActivity.kt file and refer to the following code. Below is the code for the MainActivity.kt file. Comments are added inside the code to understand the code in more detail.

Kotlin




import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.asLiveData
import androidx.lifecycle.observe
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
  
class MainActivity : AppCompatActivity() {
  
    lateinit var etName: EditText
    lateinit var etAge: EditText
    lateinit var tvName: TextView
    lateinit var tvAge: TextView
    lateinit var saveButton: Button
  
    lateinit var userManager: UserManager
    var age = 0
    var name = ""
  
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
  
        etName = findViewById(R.id.et_name)
        etAge = findViewById(R.id.et_age)
        tvName = findViewById(R.id.tv_name)
        tvAge = findViewById(R.id.tv_age)
        saveButton = findViewById(R.id.btn_save)
  
        // Get reference to our userManager class
        userManager = UserManager(this)
  
        // this function saves the data to
        // preference data store on click of
        // save Button
        buttonSave()
  
        // this function retrieves the saved data
        // as soon as they are stored and even
        // after app is closed and started again
        observeData()
    }
  
    private fun buttonSave() {
        // Gets the user input and saves it
        saveButton.setOnClickListener {
            name = etName.text.toString()
            age = etAge.text.toString().toInt()
  
            // Stores the values
            // Since the storeUser function of UserManager
            // class is a suspend function
            // So this has to be done in a coroutine scope
            GlobalScope.launch {
                userManager.storeUser(age, name)
            }
        }
    }
  
    private fun observeData() {
        // Updates age
        // every time user age changes it will be observed by userAgeFlow
        // here it refers to the value returned from the userAgeFlow function 
        // of UserManager class
        this.userManager.userAgeFlow.asLiveData().observe(this) {
            age = it
            tvAge.text = it.toString()
        }
  
        // Updates name
        // every time user name changes it will be observed by userNameFlow
        // here it refers to the value returned from the usernameFlow function 
        // of UserManager class
        userManager.userNameFlow.asLiveData().observe(this) {
            name = it
            tvName.text = it.toString()
        }
    }
}


Output:

Github repo here.



Last Updated : 24 Jan, 2021
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads