|

Jetpack component Preference DataStore in android

Sharing is caring!

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

Similar Posts

Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments