I have a LiveData
object that depends on another LiveData
. As I understand, Transformations.switchMap
should allow to chain them. But switchMap
handler is triggered only once and it doesn't react on further updates. If instead I use observe
on the first object and, when it's ready, retrieve the second, it works fine but in this case I have to do it in Activity
rather than ViewModel
. Is it possible to chain LiveData
objects, like Transformations.switchMap
, but receive all updates, not only the first one?
Here is an attempt to use switchMap
:
LiveData<Resource<User>> userLiveData = usersRepository.get();
return Transformations.switchMap(userLiveData, resource -> {
if (resource.status == Status.SUCCESS && resource.data != null) {
return apiService.cartItems("Bearer " + resource.data.token);
} else {
return AbsentLiveData.create();
}
});
Here is an approach with observe
in activity (works but requires to keep logic in activity):
viewModel.user().observe(this, x -> {
if (x != null && x.data != null) {
viewModel.items(x.data.token).observe(this, result -> {
// use result
});
}
});
I was trying to do something similar to you. I have a LiveData something
, and when that changes I want to query somethingElse
from the DB based on a property. Because the property can be null, if I query the DB with it, I'll get an exception. Therefore, if the property is null, I'm returning an empty MutableLiveData.
I have noticed, that when I returned this empty MutableLiveData, the observers that subscribed to somethingElse
were not getting any updates. I saw that on your answer you ended up using a MediatorLiveData. Then I steped through my code with the debugger and noticed that the switchMap also uses a MediatorLiveData.
After experimenting a bit, I realised that when creating the empty MutableLiveData, it's initial value is null and won't trigger any updates. If I explicitly set the value, then it will notify the observers.
somethingElse = Transformations.switchMap(something, somethingObject -> {
if (something.someProperty() != null) {
return repository.getSomethingElseByProperty(something.someProperty());
}else{
MutableLiveData<SomethingElse> empty = new MutableLiveData<>();
empty.setValue(null);//need to set a value, to force update of observers
return empty;
}
The code here has worked for me. In the question, you use an AbsentLiveData, which I don't know how it is implemented, so I'm not sure it would work exactly in that case.
As a workaround, I used MediatorLiveData
. I add the result of the first call as a source and, when it's ready, replace it with a final call:
MediatorLiveData<MyResponse> result = new MediatorLiveData<>();
LiveData<Resource<User>> source = this.get();
result.addSource(source, resource -> {
if (resource.status == Status.SUCCESS && resource.data != null) {
result.removeSource(source);
result.addSource(apiService.cartItems("Bearer " + resource.data.token), result::postValue);
}
});
return result;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With