Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 556
Philip Avatar asked Oct 18 '25 23:10

Philip


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()
like image 193
Steeve Favre Avatar answered Oct 21 '25 12:10

Steeve Favre