Selon Documentation LiveData :
La classe LiveData offre les avantages suivants:
...
Toujours mettre à jour les données: Si un cycle de vie redémarre (comme une activité qui revient à l’état initial depuis la pile arrière), il reçoit les données de localisation les plus récentes (s’il ne l’a pas déjà été).
Mais parfois, je n'ai pas besoin de cette fonctionnalité.
Par exemple, j'ai les données LiveData suivantes dans ViewModel et Observer dans Activity:
//LiveData
val showDialogLiveData = MutableLiveData<String>()
//Activity
viewModel.showMessageLiveData.observe(this, Android.Arch.lifecycle.Observer { message ->
AlertDialog.Builder(this)
.setMessage(message)
.setPositiveButton("OK") { _, _ -> }
.show()
})
Après chaque rotation, l’ancien dialogue apparaît.
Existe-t-il un moyen d'effacer la valeur stockée après son traitement ou l'utilisation incorrecte de LiveData?
La réponse d'Alex dans les commentaires est je pense exactement ce que vous recherchez. Il existe un exemple de code pour une classe appelée SingleLiveEvent . Le but de cette classe est décrit comme suit:
Une observable sensible au cycle de vie qui envoie uniquement les nouvelles mises à jour après abonnement, utilisé pour des événements tels que la navigation et les messages Snackbar.
Cela évite un problème commun avec les événements: lors de la modification de la configuration (comme la rotation) une mise à jour peut être émise si l'observateur est actif . Ce LiveData appelle l'observable uniquement s'il existe un appel explicite à setValue () ou call ().
Dans mon cas, SingleLiveEvent ne m'aide pas. J'utilise ce code:
private MutableLiveData<Boolean> someLiveData;
private final Observer<Boolean> someObserver = new Observer<Boolean>() {
@Override
public void onChanged(@Nullable Boolean aBoolean) {
if (aBoolean != null) {
// doing work
...
// reset LiveData value
someLiveData.postValue(null);
}
}
};
Je ne sais pas si cela fonctionnera dans votre cas, mais dans mon cas (augmentation/diminution du nombre d'éléments dans la pièce en cliquant sur les vues), supprimer Observer et vérifier s'il y a des observateurs actifs me laissent faire le travail
LiveData<MenuItem> menuitem = mViewModel.getMenuItemById(menuid);
menuitem.observe(this, (MenuItem menuItemRoom) ->{
menuitem.removeObservers(this);
if(menuitem.hasObservers())return;
// Do your single job here
});
});
Vous devez utiliser SingleLiveEvent pour ce cas
class SingleLiveEvent<T> : MutableLiveData<T>() {
private val pending = AtomicBoolean(false)
@MainThread
override fun observe(owner: LifecycleOwner, observer: Observer<T>) {
if (hasActiveObservers()) {
Log.w(TAG, "Multiple observers registered but only one will be notified of changes.")
}
// Observe the internal MutableLiveData
super.observe(owner, Observer<T> { t ->
if (pending.compareAndSet(true, false)) {
observer.onChanged(t)
}
})
}
@MainThread
override fun setValue(t: T?) {
pending.set(true)
super.setValue(t)
}
/**
* Used for cases where T is Void, to make calls cleaner.
*/
@MainThread
fun call() {
value = null
}
companion object {
private const val TAG = "SingleLiveEvent"
}
}
Et à l'intérieur de votre classe viewmodel, créez un objet comme:
val snackbarMessage = SingleLiveEvent<Int>()
Si vous avez besoin d'une solution simple, essayez celle-ci:
class SingleLiveData<T> : MutableLiveData<T?>() {
override fun observe(owner: LifecycleOwner, observer: Observer<in T?>) {
super.observe(owner, Observer { t ->
if (t != null) {
observer.onChanged(t)
postValue(null)
}
})
}
}
Utilisez-le comme un MutableLiveData ordinaire