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)
}
}
}
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 siequals()
rendementsfalse
.<< Snip Resternder >>
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)
}
}
}
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