Android DataStore Flow and LiveData | all preferences receive update although only one preference is updated

Viewed 755

I have an Architecture Components DataStore in my App. In this DataStore I have multiple preferences. Following a snippet of two preferences.

val calibrationFactorFlow: Flow<Float> = context.dataStore.data.map {
        preferences -> preferences[PreferencesKeys.CALIBRATION_FACTOR] ?: AppConstants.DEFAULT_CALIBRATION_FACTOR
}
suspend fun saveCalibrationToDataStore(calibrationFactor: Float) {
    context.dataStore.edit { preferences ->
        preferences[PreferencesKeys.CALIBRATION_FACTOR] = calibrationFactor
    }
}


val scaleFactorMetricFlow: Flow<Int> = context.dataStore.data.map {
        preferences -> preferences[PreferencesKeys.SCALE_FACTOR_METRIC] ?: AppConstants.DEFAULT_SCALE_FACTOR_METRIC
}
suspend fun saveScaleFactorMetricToDataStore(scaleFactor: Int) {
    context.dataStore.edit { preferences ->
        preferences[PreferencesKeys.SCALE_FACTOR_METRIC] = scaleFactor
    }
}

I use the received Flow in my ViewModel as LiveData.

val calibrationFactor: LiveData<Float> = repository.calibrationFactorFlow.asLiveData()
val scaleSelectedMetricId: LiveData<Int> = repository.scaleFactorMetricFlow.asLiveData()

The problem is, whenever I make an update to one of these preferences in the data store all other preferences receive an update. I cannot unterstand why and I cannot find anything in the documentation.

Someone has any idea why this happens or how I can prevent all preferences from receiving an update when only one preference is updated in LiveData / Flow

Thanks.

1 Answers

After further researches I found this statement in an official Android page:

Room vs DataStore If you have a need for partial updates, referential integrity, or large/complex datasets, you should consider using Room instead of DataStore. DataStore is ideal for small or simple datasets and does not support partial updates or referential integrity.

So Datastore is considered as monolithic, for partial updates we have to use another object such as Room

EDIT:

Here is the solution: use distinctUntilChanged() method on Flow

    val volUpLiveData: LiveData<Int> = mContext.dataStore.data
    .map { diags ->
        diags[tagNameVolUp] ?: -1
    }.distinctUntilChanged().asLiveData()
Related