我发现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)
}
}
}
答案 0 :(得分:5)
您可以使用以下魔术来消耗“相同的物品”:
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)
}
}
})
}
如果要检查引用相等,则为!==
。
答案 1 :(得分:1)
API中已经存在Transformations.distinctUntilChanged()
distinctUntilChanged
public static LiveData<X> distinctUntilChanged (LiveData<X> source)
创建一个新的
LiveData
对象直到该源发出一个值 LiveData值已更改。如果满足以下条件,则认为该值已更改equals()
产生false
。<<剪余物>>
答案 2 :(得分:0)
如果我们谈论MutableLiveData
,则可以创建一个类并覆盖setValue,然后仅在new value != old value
时通过super进行调用
class DistinctUntilChangedMutableLiveData<T> : MutableLiveData<T>() {
override fun setValue(value: T?) {
if (value != this.value) {
super.setValue(value)
}
}
}
答案 3 :(得分:0)
就我而言,我有非常复杂的对象,必须通过某些字段进行比较。为此,我更改了EpicPandaForce的答案:
fun <T> LiveData<T>.distinctUntilChanged(compare: T?.(T?) -> Boolean = { this == it }): LiveData<T> = MediatorLiveData<T>().also { mediator ->
mediator.addSource(this) { newValue ->
if(!newValue.compare(value)) {
mediator.postValue(newValue)
}
}
}
默认情况下,它使用标准的equals
方法,但如果需要-可以更改区分逻辑