Reputation: 2731
I'm not sure where I'm implementing MediatorLiveData incorrectly.
I have a Repository class that exposes a mutable live data object:
private MutableLiveData<List<UserTransaction>> mTransactionsLiveData
= new MutableLiveData<>();
public MutableLiveData<List<UserTransaction>> getTransactionsLiveData() {
return mTransactionsLiveData;
}
I have passed reference of this MutableLiveData
to my ViewModel
class with a getter:
public class UserTransactionsViewModel extends AndroidViewModel {
private LiveData<List<UserTransaction>> mTransactionsLiveData;
private SharedRepo mRepo;
public UserTransactionsViewModel(@NonNull Application application) {
super(application);
mRepo = new SharedRepo(application);
mTransactionsLiveData = mRepo.getTransactionsLiveData();
}
public LiveData<List<UserTransaction>> getTransactionsLiveData() {
return mTransactionsLiveData;
}
public void getUserTransactions(int userId) {
mRepo.getUserTransactions(userId);
}
}
And in my Fragment class, I am observing it:
mViewModel.getTransactionsLiveData().observe(getViewLifecycleOwner(), new Observer<List<UserTransaction>>() {
@Override
public void onChanged(List<UserTransaction> list) {
//Observing it here
loadDataIntoRecycler(list);
}
});
Where I am confused:
I am now trying to add a MediatorLiveData
to format the Data that the ViewModel
receives from the Repository
class.
So I first added a new new MediatorLiveData<>()
in the ViewModel
private MediatorLiveData<List<UserTransaction>> mediatorLiveData
= new MediatorLiveData<>();
and attached the .addSource
private MediatorLiveData<List<UserTransaction>> mediatorLiveData = new MediatorLiveData<>();
public UserTransactionsViewModel(@NonNull Application application) {
super(application);
mRepo = new SharedRepo(application);
mTransactionsLiveData = mRepo.getTransactionsLiveData();
mediatorLiveData.addSource(mTransactionsLiveData, new Observer<List<UserTransaction>>() {
@Override
public void onChanged(List<UserTransaction> userTransactions) {
Log.d(TAG, "onChanged: Formatting data...");
for(int i = 0; i < list.size(); i++){
list.get(i).setTime("Changing time");
}
}
});
}
I am confused, do I make the observer in the Fragment listen to the MediatorLiveData
, instead of the LiveData
? Because the .onChanged
method on mediatorLiveData
is never called.
Upvotes: 1
Views: 1515
Reputation: 12478
The .onChanged
method on the mediatorLiveData
is never called because it's not observed.
And, if you have already tried to observe the mediatorLiveData
from the Fragment and .onChanged
method is still not called, it means the observee is never changed. Never changed means never being setValue
or postValue
.
Like this:
mediatorLiveData.addSource(mTransactionsLiveData,
new Observer<List<UserTransaction>>() {
@Override
public void onChanged(List<UserTransaction> userTransactions) {
Log.d(TAG, "onChanged: Formatting data...");
for(int i = 0; i < list.size(); i++){
list.get(i).setTime("Changing time");
}
mediatorLiveData.setValue(list);
}
});
Or, using Transformations.map
(and Java 8 lambda) may be cleaner (while observe userTransactions
from the Fragment):
public LiveData<List<UserTransaction>> userTransactions;
userTransactions = Transformations.map(mTransactionsLiveData, list -> {
Log.d(TAG, "onChanged: Formatting data...");
for(int i = 0; i < list.size(); i++){
list.get(i).setTime("Changing time");
}
return list;
});
Upvotes: 4
Reputation: 3186
MediatorLiveData only observes its sources while it's active (has an active observer) so yes, you should observe it in your Fragment. When there are no active observers, onChanged will not be called.
Upvotes: 0