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.valueNotDistinct
that force updatesMutableStateFlow.value
.
-> Problem:MutableStateFlow.value
has 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 havevalue
property
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.