我观察到MutableLiveData
触发观察者的onChanged
,即使它的setValue
方法提供了相同的对象实例。
//Fragment#onCreateView - scenario1
val newValue = "newValue"
mutableLiveData.setValue(newValue) //triggers observer
mutableLiveData.setValue(newValue) //triggers observer
//Fragment#onCreateView - scenario2
val newValue = "newValue"
mutableLiveData.postValue(newValue) //triggers observer
mutableLiveData.postValue(newValue) //does not trigger observer
如果向setValue()
/ postValue()
提供相同或等效的实例,是否有办法避免观察者被通知两次
我尝试扩展MutableLiveData
,但这不起作用。我可能会在这里遗漏一些东西
class DistinctLiveData<T> : MutableLiveData<T>() {
private var cached: T? = null
@Synchronized override fun setValue(value: T) {
if(value != cached) {
cached = value
super.setValue(value)
}
}
@Synchronized override fun postValue(value: T) {
if(value != cached) {
cached = value
super.postValue(value)
}
}
}
您可以使用以下魔术技巧来消耗“项目相同”:
fun <T> LiveData<T>.distinctUntilChanged(): LiveData<T> = MediatorLiveData<T>().also { mediator ->
mediator.addSource(this, object : Observer<T> {
private var isInitialized = false
private var previousValue: T? = null
override fun onChanged(newValue: T?) {
val wasInitialized = isInitialized
if (!isInitialized) {
isInitialized = true
}
if(!wasInitialized || newValue != previousValue) {
previousValue = newValue
mediator.postValue(newValue)
}
}
})
}
如果你想检查参照平等,那就是!==
。
已有API:Transformations.distinctUntilChanged()
distinctUntilChanged
public static LiveData<X> distinctUntilChanged (LiveData<X> source)
创建新的
LiveData
对象在源LiveData值更改之前不会发出值。如果equals()
产生false
,则认为该值已更改。<< snip remainder >>
如果我们谈论MutableLiveData
,你可以创建一个类并覆盖setValue然后只调用super如果new value != old value
class DistinctUntilChangedMutableLiveData<T> : MutableLiveData<T>() {
override fun setValue(value: T?) {
if (value != this.value) {
super.setValue(value)
}
}
}