MutableStateFlow doesn't notify collectors if the updated value equals the old value (source). I've found a workaround for this, but it doesn't scale well for complex values.
Workaround: Duplicate data classes with copy() and lists with toList()/toMutableList().
Example 1: Simple data class WorkoutRoutine using workaround to rename name. Nothing wrong here.
data class WorkoutRoutine(
var name: String,
)
val workoutRoutine = MutableStateFlow(WorkoutRoutine("Initial"))
workoutRoutine.value.name = "Updated" // Doesn't notify collectors
workoutRoutine.value = workoutRoutine.value.copy(name = "Updated") // Workaround: works
Example 2: Complex data class WorkoutRoutine with multiple dependencies, using workaround to add a Set to an Exercise in the WorkoutRoutine: This requires a lot of copy() and toMutableList() calls, which make the code unreadable.
data class WorkoutRoutine(
var name: String,
var exercises: MutableList<Exercise> = mutableListOf(Exercise())
)
data class Exercise(
var sets: MutableList<Set> = mutableListOf(Set())
)
data class Set(
var weight: Int? = null
)
val workoutRoutine = MutableStateFlow(WorkoutRoutine("Initial"))
// Doesn't notify collectors
workoutRoutine.value.apply {
exercises = exercises.also {
it[0].sets.add(Set())
}
}
// Workaround: works
workoutRoutine.value = workoutRoutine.value.copy(
exercises = workoutRoutine.value.exercises.toMutableList().also {
it[0] = it[0].copy(sets = it[0].sets.apply { add(Set()) })
}
)
I've tried the following:
- Adding an extension value
MutableStateFlow.valueNotDistinctthat force updatesMutableStateFlow.value.
-> Problem:MutableStateFlow.valuehas to be nullable
var <T> MutableStateFlow<T?>.valueNotDistinct: T?
get() = null
set(newValue) {
value = null
value = newValue
}
- Using
MutableSharedFlow, which doesn't check for equality
-> Problem: Not as performant, doesn't havevalueproperty
What I want is to simply notify collectors on every emit, but I don't know how to do that, because there doesn't seem to be a "force notify" function for MutableStateFlow.