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

问题描述 投票:1回答:1

我具有以下具有MutableLiveData data的ViewModel和另一个从ones派生的LiveData data,该方式只有在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为空,如何解决此问题?

android kotlin android-livedata android-jetpack android-viewmodel
1个回答
0
投票

也许我丢失了一些东西,但是这种行为似乎是我所期望的...

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

没有doSomething():

  1. 创建Livedata
  2. 添加Dummy(1, "Init")
  3. 开始监听片段:由于数字为1,它会通过您的过滤器,片段会接收到它

使用doSomething():

  1. 创建Livedata
  2. 添加Dummy(1, "Init")
  3. 添加Dummy(2, "Do something")LiveData仅保留最后一个值,因此,如果没有人注意,则第一个值会丢失)
  4. 开始监听片段:由于数字为0,因此该值将被过滤且片段不接收任何内容

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

© www.soinside.com 2019 - 2024. All rights reserved.