列表的 LiveData 通知观察者而不调用 setValue 或 postValue
LiveData of a list notifies observers without calling setValue or postValue
我的视图模型中有这样一个 MutableLiveData
:
val liveData = MutableLiveData<ArrayList<*>>()
我将端点调用的结果添加到此 LiveData
,如下所示:
liveData.value?.addAll(myList)
据我所知,MutableLiveData
不应该通知它是 Observer
s,除非你对它执行 setValue
或 postValue
但此时我的代码是 运行,Observer
会收到更改通知。
这怎么可能?
更新:
我遇到了一个更奇怪的行为,这个测试通过了但是列表被打印了一次:[]
@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)
}
当 LiveData
发送通知时,LiveData
不会发送该项目的副本。相反,它只是传递对持有的同一实例的引用。
这意味着如果您像这样修改 LiveData
中的数据:
myLiveData.value?.addAll(listOf(1, 2, 3, 4))
观察者先前收到的 ArrayList
对象也将被修改 而 Observer.onChanged()
不会被调用 ,因为它们是同一个对象。这就是为什么在 LiveData
或任何 Observer/reactive 模式中使用可变对象通常不是一个好主意。
要验证 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())
}
我的视图模型中有这样一个 MutableLiveData
:
val liveData = MutableLiveData<ArrayList<*>>()
我将端点调用的结果添加到此 LiveData
,如下所示:
liveData.value?.addAll(myList)
据我所知,MutableLiveData
不应该通知它是 Observer
s,除非你对它执行 setValue
或 postValue
但此时我的代码是 运行,Observer
会收到更改通知。
这怎么可能?
更新:
我遇到了一个更奇怪的行为,这个测试通过了但是列表被打印了一次:[]
@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)
}
当 LiveData
发送通知时,LiveData
不会发送该项目的副本。相反,它只是传递对持有的同一实例的引用。
这意味着如果您像这样修改 LiveData
中的数据:
myLiveData.value?.addAll(listOf(1, 2, 3, 4))
观察者先前收到的 ArrayList
对象也将被修改 而 Observer.onChanged()
不会被调用 ,因为它们是同一个对象。这就是为什么在 LiveData
或任何 Observer/reactive 模式中使用可变对象通常不是一个好主意。
要验证 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())
}