web-dev-qa-db-fra.com

Comment émettre des valeurs distinctes de Mutablelivedata?

J'ai observé que MutableLiveData déclenche onChanged d'un observateur même si la même instance d'objet est fournie à sa méthode 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

Y a-t-il un moyen d'éviter un observateur être notifié deux fois si la même ou une instance équivalente est fournie à setValue()/postValue()

J'ai essayé de prolonger MutableLiveData mais cela n'a pas fonctionné. Je me manquerai quelque chose ici

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)
        }
    }
}
9
Pravin Sonawane

Il y a déjà dans API : Transformations.DistentionTontilhanged ()

distinctuntilhanged

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

Crée un nouvel objet LiveData Objet n'émet aucune valeur tant que la valeur de la source LiveTa a été modifiée. La valeur est considérée comme modifiée si equals() rendements false.

<< Snip Resternder >>

8
Jurij Pitulja

Si nous parlons de MutableLiveData, vous pouvez créer une classe et remplacer SETValue, puis seul appeler super si new value != old value

class DistinctUntilChangedMutableLiveData<T> : MutableLiveData<T>() {
    override fun setValue(value: T?) {
        if (value != this.value) {
            super.setValue(value)
        }
    }
}
2
Kuno

Dans mon cas, j'ai des objets assez complexes que je dois comparer par certains champs. Pour cela, j'ai changé la réponse d'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)
        }
    }
}

Par défaut, il utilise la méthode standard equals, mais si vous avez besoin, vous pouvez modifier la logique de distinction

1
Andrey Turkovsky