【问题标题】:LiveData of a list notifies observers without calling setValue or postValue列表的 LiveData 通知观察者而不调用 setValue 或 postValue
【发布时间】:2019-07-10 04:34:57
【问题描述】:

我的视图模型中有这样的MutableLiveData

val liveData = MutableLiveData<ArrayList<*>>()‍‍‍‍‍

我将端点调用的结果添加到此LiveData,如下所示:

liveData.value?.addAll(myList)

据我所知,MutableLiveData 不应该通知它是 Observers,除非您在其上执行 setValuepostValue 但此时当我的代码运行时,Observers 会收到通知变化。

这怎么可能?


更新:

我遇到了一个更奇怪的行为,这个测试通过了,但是列表被打印了一次:[]

    @Test
    fun `strange live data behavior`() {
        val myLiveData = MutableLiveData<ArrayList<Int>>()
        val observer = mock() as Observer<ArrayList<Int>>
        myLiveData.observeForever(observer)
        myLiveData.observeForever { println(it) }
        myLiveData.value = ArrayList()
        verify(observer).onChanged(ArrayList())
        myLiveData.value?.addAll(listOf(1, 2, 3, 4))
        val result = ArrayList<Int>()
        result.add(1)
        result.add(2)
        result.add(3)
        result.add(4)
        verify(observer).onChanged(result)
    }

【问题讨论】:

  • 还有一种情况是通知Observer。当Observer 附加到LiveData 并且LiveData 已经包含一个值时,Observer 将立即收到通知。
  • 是的,但即使在那之后也会发生这种情况
  • @SanlokLee 我已经用更多信息更新了问题
  • 我明白你现在的意思了。我会尽快附上答案。

标签: kotlin android-livedata mutablelivedata


【解决方案1】:

LiveData 发送通知时,LiveData 不会发送该项目的副本。相反,它只是将引用传递给持有的同一个实例。

这意味着如果你像这样修改LiveData里面的数据:

myLiveData.value?.addAll(listOf(1, 2, 3, 4))

观察者之前收到的ArrayList 对象也将被修改不会调用Observer.onChanged(),因为它们是同一个对象。这就是为什么在LiveData 或任何观察者/反应模式中使用可变对象通常不是一个好主意。

要验证onChanged() 实际上只调用了一次,请在测试末尾添加以下行:

    @Test
    fun `strange live data behavior`() {
        val myLiveData = MutableLiveData<ArrayList<Int>>()
        val observer = mock() as Observer<ArrayList<Int>>
        myLiveData.observeForever(observer)
        myLiveData.observeForever { println(it) }
        myLiveData.value = ArrayList()
        verify(observer).onChanged(ArrayList())
        myLiveData.value?.addAll(listOf(1, 2, 3, 4))
        val result = ArrayList<Int>()
        result.add(1)
        result.add(2)
        result.add(3)
        result.add(4)
        verify(observer).onChanged(result)

        // Below should pass because onChanged is only called once.
        verify(observer, times(1)).onChanged(any()) 
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 2018-07-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多