Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android MediatorLiveData observer

I'm a bit confused on why the following code doesn't work:

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

This code seems straightforward, however the debugger doesn't enter the callback and nothing is logged to the console...

Edit: shouldn't this work then?

    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!");
like image 203
html_programmer Avatar asked Aug 14 '17 17:08

html_programmer


People also ask

What is mediator live data in Android?

While the MediatorLiveData is a subclass of LiveData, it acts as LiveData itself. It allows us to merge multiple LiveData sources into one single LiveData which we then can observe.

Can we use LiveData without ViewModel?

No, It is not mandatory to use LiveData always inside ViewModel, it is just an observable pattern to inform the caller about updates in data.

Why use flow instead of LiveData?

StateFlow and LiveData have similarities. Both are observable data holder classes, and both follow a similar pattern when used in your app architecture. The StateFlow and LiveData do behave differently: StateFlow requires an initial state to be passed into the constructor, while LiveData does not.

What are different types of LiveData?

Types in LiveData There are subclasses in LiveData that are useful for their properties when updating the UI. LiveData is immutable by default. By using LiveData we can only observe the data and cannot set the data. MutableLiveData is mutable and is a subclass of LiveData.


2 Answers

This answer is largely reproduction of what @CommonsWare has already shared in the comment section above.

In order for the callback on MediatorLiveData's addSource method to be triggered, the MediatorLiveData object needs to be observed itself as well.

The logic behind this is that the 'mediator' mediates between a LiveData object that it observes, and a final consumer of the data. The mediator is hence an observer and observable simultaneously, and the callback on addSource won't be triggered for the mediator when there are no active observers.

As an example; according to Google's Android Architecture Components, an activity or fragment could have an observer observing a mediator on the ViewModel, which in turn may observe other LiveData objects that are handled within the ViewModel or a referenced to an utility class.

@CommonsWare pointed out the use of the Transformation class that exposes methods map and switchMap, but these were not within scope of my use case although they are worth checking out.

like image 90
html_programmer Avatar answered Sep 23 '22 12:09

html_programmer


I got here since I had more or less the same experience, but instead with MediatorLiveData.getValue(). I wasn't aware that was a problem until I faced it big time. My problem can be stated like this:

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

I know it's a bit simplified, but nevertheless MediatorLiveData.getValue() will not contain "bla" and in that way you never really know if you can trust getValue() unless you're 100% sure it is active (has more than one oberserver).

Same issue is the case for Transformations.map(...) and TransformationsswitchMap(...), where getValue() of the returned LiveData doesn't necessarily returns the newest value unless it's observed.

like image 32
Anigif Avatar answered Sep 20 '22 12:09

Anigif