Open In App

Jetpack DataStore in Android

Improve
Improve
Like Article
Like
Save
Share
Report

Jetpack DataStore is a data storage solution that uses protocol buffers to store key-value pairs or typed objects. DataStore stores data asynchronously, reliably, and transactionally using Kotlin coroutines and Flow. In this article, we will look at why we need Jetpack DataStore Preferences, how to build them in our Android application, and how to move our SharedPreferences to DataStore Preferences.

The following topics will be discussed in the blog:

  1. Why should you use Jetpack DataStore?
  2. DataStore Preferences vs. SharedPreferences
  3. Jetpack DataStore Preferences Implementation
  4. Transferring SharedPreferences to DataStore Preferences

But, First and foremost: 

1. Why is there a new Jetpack DataStore?

According to the official documentation:

  • Jetpack DataStore is a persistent and enhanced data store, which is here to revolutionize how we store prefs.
  • It is based on Coroutines and Flows in Kotlin.
  • Data is saved asynchronously, consistently, and transactionally, eliminating the majority of SharedPreferences’ shortcomings.

The above-mentioned enhancements are fantastic.

Example: It is assumed that you are working on an Android application with a high number of downloads, that the program is available on Google Play, and that it has undergone several upgrades and bug patches over time. As a result, the app began to get ANR at some point (Application Not Responding). The cause of ANR is that the program is doing a long-running operation on the UI Thread. (Longer than 5 seconds)

2. What was the purpose of this ANR?

The main issue was that our shared preferences file had grown too large as we continued to add new key-value pairs one by one. On the UI Thread, we were attempting to retrieve the value for a specific key as soon as the program launched. However, when you visit SharedPreferences for the first time, it reads the entire file and loads the contents into memory. And this was occurring on UI Thread for us.

This is an input/output operation. It may take some time. In our instance, it was leading to ANR for the larger file. Furthermore, the present implementation of Jetpack DataStore discourages data reading on the UI Thread. This was one of my favorite aspects of it. And now, we’re integrating Jetpack DataStore into our app. Let’s compare SharedPreferences to DataStore Preferences

DataStore Preferences

SharedPreferences

Has async API Can make async API calls
This is not encouraged by DataStore Preferences. SharedPreferences give a simple Synchronous API, however, it is not safe to use on the UI thread.
DataStore Preferences ensure consistency. This in contrast does not ensure that consistency
DataStore Preferences allow error handling No error handling in SharedPrefs
DataStore Preferences by default support the Kotlin Coroutines Flow API. The shared prefs need additional configuration for making the coroutines flow.

3. Jetpack DataStore Preferences Implementation

Include the following dependency in your app’s build.gradle file.

implementation "androidx.datastore:datastore-preferences:1.0.0"

GeekTip: Always try to use the latest release.

Now, similarly to the SharedPreferences object, we must build the DataStore Preferences object.

Kotlin




val gfgDataStore: DataStore<Preferences> =
    context.createDataStore(name = "gfg-datastore")
    // A data store object sample


Then we construct two extension functions to read and write data. This is only for your convenience.

Kotlin




fun <gfg> DataStore<Preferences>.getValueFlow(
    your_key: Preferences.Key<gfg>,
    someDefaultValue: gfg
    // Value is gfg here
): Flow<gfg> {
    return this.data
        .catch { exception ->
            if (exception is IOException) {
                emit(emptyPreferences())
            } else {
                // Exception handling
                throw exception
            }
        }.map { preferences ->
            preferences[your_key] ?: someDefaultValue
        }
}
  
suspend fun <gfg> DataStore<Preferences>.setValue(your_key: Preferences.Key<gfg>, value: gfg) {
    this.edit { preferences ->
        preferences[your_key] = value
    }
}


Then, as seen below, we establish Preferences Keys:

Kotlin




companion object {
    private val GEEKSFORGEEKS = preferencesKey<String>("spandan-saxena")
}


Now, that’s how we read the following data from the DataStore Preferences:

Kotlin




sampleViewModel.launch {
    dataStore.getValueFlow(GEEKSFORGEEKS, "")
        .collect { value ->
            // get the value and then use it
        }
}


We may manage the problem in this case by using the catch operator on the flow.

Kotlin




sampleViewModel.launch {
    dataStore.getValueFlow(GEEKSFORGEEKS, "")
        .catch {
            // exception handling
        }
        .collect { value ->
            // collect the value
        }
}


This is how we can easily incorporate it into our Android app. Let us now discuss the conversion from SharedPreferences to DataStore Preferences.

4. Transferring SharedPreferences to DataStore Preferences

When it comes to migration, DataStore takes care of everything. We just need to supply the names of the SharedPreferences. For example, if the name of SharedPreferences is “gfg-prefs,” we must perform the following:

Kotlin




val sampleDataStore: DataStore<Prefs> =
    context.createDataStore(
        name = "gfg-prefs",
        migrations = listOf(SharedPreferencesMigration(context, "gfg-prefs"))
    )


Conclusion

We can see that there are other alternatives accessible, which we may employ based on our use-cases. Migrating from SharedPreferences to DataStore Preferences is made much easier in this manner. SharedPreferences has numerous disadvantages, including asynchronous API that may look safe to call on the UI thread, no method for reporting failures, no transactional API, and more. DataStore is a substitute for SharedPreferences that address the majority of these issues. DataStore offers a completely asynchronous API built using Kotlin coroutines and Flow that manages data migration, data consistency, and data corruption.



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