5

MutableStateFlow如果更新的值等于旧值(来源),则不会通知收集器。我找到了一种解决方法,但它不能很好地适应复杂的值。

解决方法:使用/复制数据类copy()和列表。toList()toMutableList()

示例 1:WorkoutRoutine使用变通方法重命名的简单数据类name。这里没有错。

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

示例 2:WorkoutRoutine具有多个依赖项的复杂数据类,使用解决方法将 a 添加Set到: 这需要大量的Exerciseand调用,这使得代码不可读。WorkoutRoutinecopy()toMutableList()

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()) })
    }
)

我尝试了以下方法:

  • MutableStateFlow.valueNotDistinct添加强制更新的扩展值MutableStateFlow.value
    -> 问题:MutableStateFlow.value必须可以为空
var <T> MutableStateFlow<T?>.valueNotDistinct: T?
    get() = null
    set(newValue) {
        value = null
        value = newValue
    }
  • 使用MutableSharedFlow不检查相等性
    -> 问题:性能不高,没有value属性

我想要的是在每次发射时简单地通知收集器,但我不知道该怎么做,因为 MutableStateFlow 似乎没有“强制通知”功能。

4

1 回答 1

1

StateFlow 文档说明了这一点:

强基于平等的合并

状态流中的值使用 Any.equals 比较以类似于 distinctUntilChanged 运算符的方式进行合并。它用于将传入的更新与 MutableStateFlow 中的值合并,并在新值等于先前发出的值时抑制向收集器发出值。未指定违反 Any.equals 合同的类的状态流行为。

一种解决方法可能是覆盖equals始终返回的方法false。因此,数据类对您的情况没有帮助。

class WorkoutRoutine() {
    ...
    override fun equals(other: Any?): Boolean {
        return false
    }    
}
于 2020-12-20T22:01:18.970 回答