Jetpack component Preference DataStore in android

Hello everyone, In this article we will learn about the new Jetpack component DataStore for storing the data like shared preference. Jetpack DataStore is a data storage solution. It allows us to store key-value pairs (like SharedPreferences) or typed objects with protocol buffers. DataStore uses Kotlin and Coroutines + Flow to store data synchronously with consistency and transaction support. In short, it’s the new data storage solution which is the replacement of SharedPreferences.

What Data Store?

  1. From the definition it is clear that used the Kotlin core feature like Coroutines + Flow to store the data.
  2. SharedPreference has some limitation like it is relies on Synchronous which is not safe for main thread, and we need to manually switch to thread if needed. while Data Store is safe for UI thread because it is use Coroutines Dispatchers.IO thread.
  3. The best of all is that as it uses Kotlin flow which can be used as liveData using asLiveData() or Flow, so in this way, you can also make it lifecycle aware.
  4. SharedPreference does not throw IO exception if something happen wrong.
  5. SharedPreference is not type safe, while Data Store is type safe by using protocol buffer.

How to use the Data Store?

Let’s check the implementation part to use the Data Store.

First we need to add this dependency to our app.gradle file

// Preferences DataStore
   implementation "androidx.datastore:datastore-preferences:1.0.0"

Ok great, let say an example of Data Store. In our app we use multi language support based on county. User can select any language corresponding to prefer language. This user preference for language need to save to use in the app. As we know that Data Store use the Coroutines Flow then we need to create the set and get function of update state should be suspended. Let me create class of LanguageManager.kt.

class LanguageManager(private val context: Context) {

    val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "language_pref")

    companion object {
        val LAST_LANGUAGE_KEY = stringPreferencesKey(name = "language")
    }

    suspend fun setLanguagePref(language: String) {
        context.dataStore.edit { preference ->
            preference[LAST_LANGUAGE_KEY] = language
        }
    }

    val getLanguagePref: Flow<String> = context.dataStore.data
        .map { preferences ->
            preferences[LAST_LANGUAGE_KEY] ?: ""
        }
}

Here I use my preferenceDataStore name is “language_pref” and I use the preference to store any data in key value pair which I use the key “language”. Here I used tow function, one is use for store the data in DataStore and another one use to get the data from the DataStore.

Now I will use this LanguageManager instance in my ViewModel class with viewModel Scope to get aware the life cycle.

class LanguageViewModel(private val languageManager: LanguageManager) : ViewModel() {

    private val _languageLiveData = SingleLiveEvent<Resource<String>>()
    val languageLiveData: SingleLiveEvent<Resource<String>>
        get() = _languageLiveData

    fun setLanguagePref(language: String) {
        viewModelScope.launch {
            languageManager.setLanguagePref(language)

        }
    }

    fun getLanguage() {
        viewModelScope.launch {
            try {
                languageManager.getLanguagePref.collect {
                    _languageLiveData.value = Resource.success(it)
                }
            } catch (e: Throwable) {
                _languageLiveData.value = Resource.error(e.localizedMessage.toString(), null)
            }
        }
    }
}

Let me use this viewModel in our activity class.

class LanguageActivity: AppCompatActivity() {

    private var viewModel: LanguageViewModel?= null
    private var selectedLanguage: String?= null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_language)

      viewModel = ViewModelProviders.of(this, viewModelFactory { LanguageViewModel(
            LanguageManager(this)
        ) }).get(LanguageViewModel::class.java)

        setUpObserver()
        viewModel?.getLanguage()
        button.setOnClickListener {
            if (selectedLanguage == LanguagePref.HINDI.name) {
                viewModel?.setLanguagePref(LanguagePref.ENGLISH.name)
            }else{
                viewModel?.setLanguagePref(LanguagePref.HINDI.name)
            }
            viewModel?.getLanguage()
        }


    }

    private fun setUpObserver(){
        viewModel?.languageLiveData?.observe(this, Observer {
            when(it.status){
                Status.SUCCESS -> {
                    selectedLanguage = it.data
                    textView.text = selectedLanguage
                }
                Status.ERROR -> {
                    selectedLanguage = ""
                }
            }
        })
    }

}

Here while click on button, we are storing the value of selected language to DataStore and getting the value back by using the live data change.

 

That’s it 😍. We have implemented PreferencesDataStore now. 😍 In my next article we will learn about the migration from SharedPreference to DataStore as well as Proto DataStore. Happy Coding.

 

 

 

0 0 votes
Article Rating

Recent Posts

Hide your production API key or any sensitive data in Android

Hi everyone, In this article, we are going to learn how to hide the production… Read More

2 years ago

How to handle the localisation or multi language support in android with examples?

Hello everyone, Today in this article, we are going to learn about localisation to support… Read More

2 years ago

How to convert any callback to Coroutines and use them in Kotlin Android?

Hello everyone, In this article, we are going to learn something to handle the callback… Read More

2 years ago

Request Permission Launcher with Kotlin in Android

In this article, we are learning about the run time permissions for request permission launchers.… Read More

2 years ago

Implement the SMS User Consent API and SMS Retriever API in Android

Hello everyone. In my last tutorial, we learned about the Jetpack Compose introduction and about applying the… Read More

3 years ago

Jetpack Compose Coroutine flow with LiveData/ViewModel in Android

Hello everyone, In this article, we are going to learn about the Jetpack Compose with… Read More

3 years ago