如何从MutableLiveData发出不同的值?

问题描述 投票:2回答:3

我观察到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)
        }
    }
}
android android-livedata mutablelivedata
3个回答
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)
            }
        }
    })
}

如果你想检查参照平等,那就是!==


2
投票

已有API:Transformations.distinctUntilChanged()

distinctUntilChanged

public static LiveData<X> distinctUntilChanged (LiveData<X> source)

创建新的LiveData对象在源LiveData值更改之前不会发出值。如果equals()产生false,则认为该值已更改。

<< snip remainder >>


0
投票

如果我们谈论MutableLiveData,你可以创建一个类并覆盖setValue然后只调用super如果new value != old value

class DistinctUntilChangedMutableLiveData<T> : MutableLiveData<T>() {
    override fun setValue(value: T?) {
        if (value != this.value) {
            super.setValue(value)
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.