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

Android 为什么调用两次时会忽略Livedata setValue?,android,kotlin,android-livedata,android-jetpack,android-viewmodel,Android,Kotlin,Android Livedata,Android Jetpack,Android Viewmodel,我有下面的ViewModel,其中包含可变的LiveDatadata和另一个LiveDataones,它是从data派生的,只有当data.number等于1时,它才会更新其值 class DummyViewModel : ViewModel() { private val data = MutableLiveData<Dummy>() val ones = data.mapNotNull { it.takeIf { it.number == 1 } }

我有下面的ViewModel,其中包含可变的LiveData
data
和另一个LiveData
ones
,它是从
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
}
class DummyViewModel:ViewModel(){
private val data=MutableLiveData()
val ones=data.mapNotNull{it.takeIf{it.number==1}
初始化{
data.value=Dummy(1,“初始”)
doSomething()
}
有趣的事{
data.value=Dummy(2,“做点什么”)
}
}
数据类虚拟(val编号:Int,val文本:String)
fun LiveData.mapNotNull(映射器:(T)->Y?):LiveData{
val mediator=MediatorLiveData()
mediator.addSource(此){item->
val mapped=映射器(项目)
如果(映射!=null){
mediator.value=mapped
}
}
返回调解人
}
在我的片段中,我观察到了
。但是,如果我执行
doSomething
,我不会在片段中收到任何更新。如果我不执行
doSomething
,则虚拟
Init
将正确地出现在
ones
中,我将收到一个更新


这里发生了什么?为什么
ones
是空的,我怎样才能克服这个问题?

也许我遗漏了什么,但这种行为似乎是我所期待的

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

不使用doSomething():

  • 创建
    Livedata
  • 添加
    Dummy(1,“Init”)
  • 开始监听片段:因为数字是
    1
    ,所以它会通过你的过滤器,片段会收到它
  • 使用doSomething():

  • 创建
    Livedata
  • 添加
    Dummy(1,“Init”)
  • 添加
    Dummy(2,“做点什么”)
    LiveData
    只保留最后一个值,因此如果没有人观察,第一个值就会丢失)
  • 开始在片段中侦听:因为数字是
    2
    ,所以该值将被过滤,而片段将不接收任何内容
  • 有点离题:像这样为ViewModel案例编写测试总是好的,因为您将能够隔离问题并快速找到真正的原因


    编辑:还要注意,您的筛选器仅用于观察,在将值放入
    LiveData

    时不会应用它,您对此
    it.takeIf{it.number==1}有何期望
    ?@StanislavBondar我希望
    只在对象的
    number
    属性为
    1
    时才更新其值。这当然只是为了演示。@StanislavBondar让我吃惊的是,如果调用了
    doSomething
    ,则第一个
    data.value=Dummy(1,“Init”)
    没有设置。