web-dev-qa-db-fra.com

Observateur Android MediatorLiveData

Je suis un peu confus sur pourquoi le code suivant ne fonctionne pas:

MutableLiveData<String> mutableTest = new MutableLiveData<>();
MediatorLiveData<String> mediatorTest = new MediatorLiveData<>();
mediatorTest.addSource(mutableTest, test -> {
    Timber.d(test);
});
mutableTest.setValue("bla!");

Ce code semble simple, cependant le débogueur n'entre pas le rappel et rien n'est connecté à la console ... 

Edit: cela ne devrait-il pas fonctionner alors? 

    MutableLiveData<String> mutableTest = new MutableLiveData<>();
    MediatorLiveData<String> mediatorTest = new MediatorLiveData<>();
    mediatorTest.observe(loginActivity, str -> Timber.d(str));
    mediatorTest.addSource(mutableTest, str -> Timber.d(str));
    mutableTest.setValue("bla!");
5
Trace

Cette réponse est en grande partie une reproduction de ce que @CommonsWare a déjà partagé dans la section commentaire ci-dessus. 

Pour que le rappel sur la méthode addSource de MediatorLiveData soit déclenché, l'objet MediatorLiveData doit également être observé lui-même. 

La logique derrière cela est que le "médiateur" sert d'intermédiaire entre un objet LiveData qu'il observe et un consommateur final des données. Le médiateur est donc à la fois observateur et observable, et le rappel sur addSource ne sera pas déclenché pour le médiateur en l'absence d'observateur actif. 

Par exemple; Selon les composants d'architecture Android de Google, une activité ou un fragment peut avoir un observateur observant un médiateur sur le ViewModel, lequel peut alors observer d'autres objets LiveData gérés dans ViewModel ou référencés à une classe d'utilitaires. 

@CommonsWare a souligné l'utilisation de la classe Transformation qui expose les méthodes map et switchMap, mais celles-ci n'étaient pas couvertes par mon cas d'utilisation bien qu'elles valent la peine d'être vérifiées. 

20
Trace

Je suis arrivé ici depuis que j'ai eu plus ou moins la même expérience, mais plutôt avec MediatorLiveData.getValue(). Je n'étais pas au courant que c'était un problème jusqu'à ce que j'y fasse face. Mon problème peut être énoncé comme ceci:

MutableLiveData<String> mutableTest = new MutableLiveData<>();
MediatorLiveData<String> mediatorTest = new MediatorLiveData<>();
mediatorTest.addSource(mutableTest, test -> {
    mediatorTest.value = test;
});
mutableTest.setValue("bla!");
mediatorTest.getValue(); // will be null

Je sais que c'est un peu simplifié, mais néanmoins MediatorLiveData.getValue() ne contiendra pas "bla" et ainsi vous ne saurez jamais vraiment si vous pouvez faire confiance à getValue() si vous n'êtes pas sûr à 100% qu'il est actif (a plus d'un oberserver).

Même problème pour Transformations.map(...) et TransformationsswitchMap(...), où getValue() de la LiveData renvoyée ne renvoie pas nécessairement la valeur la plus récente, sauf si elle est observée.

1
Anigif