为什么调用两次时Livedata setValue会被忽略?

Why is Livedata setValue ignored when called twice?

我有以下带有 MutableLiveData data 和另一个从 data 派生的 LiveData ones 的 ViewModel,它仅在 data.number 时才更新其值等于 1.

class DummyViewModel : ViewModel() {

    private val data = MutableLiveData<Dummy>()
    val ones = data.mapNotNull { it.takeIf { it.number == 1 } }

    init {
        data.value = Dummy(1, "Init")
        doSomething()

    }

    fun doSomething() {
        data.value = Dummy(2, "Do something")
    }
}

data class Dummy(val number: Int, val text: String)

fun <T, Y> LiveData<T>.mapNotNull(mapper: (T) -> Y?): LiveData<Y> {
    val mediator = MediatorLiveData<Y>()
    mediator.addSource(this) { item ->
        val mapped = mapper(item)
        if (mapped != null) {
            mediator.value = mapped
        }
    }
    return mediator
}

我在片段中观察到 ones。但是,如果我执行 doSomething,我的片段中不会收到任何更新。如果我不执行 doSomething,虚拟 Init 正确存在于 ones 中,我会收到更新。

这里发生了什么?为什么 ones 是空的,我该如何解决这个问题?

也许我遗漏了什么,但这种行为似乎符合我的预期...

让我们尝试按顺序重现这两种情况。

没有 doSomething() :

  1. 创建Livedata
  2. 添加Dummy(1, "Init")
  3. 开始在片段中收听:因为数字是 1,它通过了您的过滤器并且片段接收到它

用 doSomething():

  1. 创建Livedata
  2. 添加Dummy(1, "Init")
  3. 添加Dummy(2, "Do something")LiveData只保留最后一个值,所以如果没有人观察,第一个值就会丢失)
  4. 开始在片段中监听:因为数字是 2,值被过滤,片段什么也接收不到

一点题外话:像这样为 ViewModel 案例编写测试总是好的,因为您将能够隔离问题并快速找到真正的原因。

编辑:另请注意,您的过滤器仅用于观察,在将值放入 LiveData 时不会应用它。