web-dev-qa-db-fra.com

Comment effacer la valeur stockée LiveData?

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?

22
Kamer358

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 ().

29
Lyla

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);
        }
    }
};
4
Final12345

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

                });
});  
1
Jurij Pitulja

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>()
1
Ankit Bisht

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

0
Nynuzoud