Observing Android Jetpack DataStore Value Change

5.9k views Asked by At

Am I missing something or is it not possible to attach a listener to the new Android Jetpack Preference Datastore? I thought the whole point of using Flow is that we can call flow.toLiveData() on the Preference Datastore and observe changes to the value changes.

Here is how I am getting a Flow from the Datastore.

 val taxRatePreferenceFlow: Flow<TaxRate> = dataStore.data
        .catch { exception ->
            if (exception is IOException){
                emit(emptyPreferences())
            } else {
                throw exception
            }
        }.map { preferences ->
            val name = preferences[PreferencesKeys.TAX_LABEL] ?: "Tax"
            val rate = preferences[PreferencesKeys.TAX_RATE] ?: Constants.DEFAULT_TAX_RATE.toFloat()
            val type = TaxType.valueOf(preferences[PreferencesKeys.TAX_TYPE] ?: TaxType.ON_ITEMS.name)
            TaxRate(name, rate, type)
        }

I was hoping to convert the Flow to a LiveData like so in the ViewModel and listen for changes until the observers are removed.

totalAmountLiveData.addSource(taxRateFlow.asLiveData()){ taxtRate ->
            taxtRate?.let {
                updateTaxAmount(it)
            }
        }

However this observer only emits the saved value and does not update as the values are updated. Exiting and re-entering the screen shows the updated value.

And here is how I update each value in the DataStore

 suspend fun updateTaxLabel(newTaxLabel: String){
        dataStore.edit { preferences ->
            preferences[PreferencesKeys.TAX_LABEL] = newTaxLabel
        }
    }

What am I missing, should I be using collect instead of map? If yes, can someone show me an example of how to use Flow collect in this context.

1

There are 1 answers

7
Priyansh Kedia On

You can directly observe the flow as a liveData, no need to add it as source for another live data.

Your code would change from

totalAmountLiveData.addSource(taxRateFlow.asLiveData()){ taxtRate ->
        taxtRate?.let {
            updateTaxAmount(it)
        }
    }

to

taxRateFlow.asLiveData().observe(this */ lifeCycleOwner */) {
            updateTaxAmount(it)
}

In this case you can directly see your data changing the datastore and perform the functions accordingly.