My question is related to ViewModel second time returns null wherein I am not getting callback inobserve
function if I make a repeated call to server. Following is the code I am using -
@Singleton
public class NetworkInformationViewModel extends AndroidViewModel {
private LiveData<Resource<NetworkInformation>> networkInfoObservable;
private final APIClient apiClient;
@Inject
NetworkInformationViewModel(@NonNull APIClient apiClient, @NonNull Application application) {
super(application);
this.apiClient = apiClient;
getNetworkInformation();
}
public LiveData<Resource<NetworkInformation>> getNetworkInfoObservable() {
return networkInfoObservable;
}
// making API calls and adding it to Observable
public void getNetworkInformation() {
networkInfoObservable = apiClient.getNetworkInformation();
}
}
In Activity, the ViewModel is defined as followed -
final NetworkInformationViewModel networkInformationViewModel =
ViewModelProviders.of(this, viewModelFactory).get(NetworkInformationViewModel.class);
observeViewModel(networkInformationViewModel);
The observeViewModel
function is used to add observable on ViewModel
.
public void observeViewModel(final NetworkInformationViewModel networkInformationViewModel) {
networkInformationViewModel.getNetworkInfoObservable()
.observe(this, networkInformationResource -> {
if (networkInformationResource != null) {
if (networkInformationResource.status == APIClientStatus.Status.SUCCESS) {
Timber.d("Got network information data");
} else {
final Throwable throwable = networkInformationResource.throwable;
if (throwable instanceof SocketTimeoutException) {
final NetworkInformation networkInformation = networkInformationResource.data;
String error = null;
if (networkInformation != null) {
error = TextUtils.isEmpty(networkInformation.error) ? networkInformation.reply : networkInformation.error;
}
Timber.e("Timeout error occurred %s %s", networkInformationResource.message, error);
} else {
Timber.e("Error occurred %s", networkInformationResource.message);
}
if (count != 4) {
networkInformationViewModel.getNetworkInformation();
count++;
// Uncommenting following line enables callback to be received every time
//observeViewModel(networkInformationViewModel);
}
}
}
});
}
Uncommenting the following line in above function allows the callback to come everytime, but there has to be a proper way of doing this.
//observeViewModel(networkInformationViewModel);
Please note:- I don't need RxJava implementation for implementing this.
Right now in
getNetworkInformation()
you are:LiveData
LiveData
usingsetValue
Instead, you should have a single
LiveData
forAPIClient
created as a member variable, then in getNetworkInformation() just update that memberLiveData
.More generally, your
APIClient
is a data source. For data sources, you can have them contain member LiveData objects that update when the data changes. You can provide getters to those LiveData objects to make them accessible in ViewModels, and ultimately listen to them in your Activities/Fragments. This is similar how you might take another data source, such as Room, and listen to a LiveData returned by Room.So the code in this case would look like:
Then in your ViewModel...
Your activity can be the same as you originally coded it; it will just get and observe the LiveData from the ViewModel.
So what is Transformations.switchMap for?
switchMap
isn't necessary here because you don't need to change the underlyingLiveData
instance inAPIClient
. This is because there's really only one piece of changing data. Let's say instead your APIClient needed 4 different LiveData for some reason, and you wanted to change whichLiveData
you observed:Then let's say that your fetchNetworkInformation would refer to different LiveData to observe depending on the situation. It might look like this:
In this case the actual
LiveData
coming fromgetNetworkInformation
is changes, and you're also using some sort of parameter to determine which LiveData you want. In this case, you'd use aswitchMap
, because you want to make sure that the observe statement you called in your Activity/Fragment observes the LiveData returned from yourAPIClient
, even if you change the underlying LiveData instance. And you don't want to call observe again.Now this is a bit of an abstract example, but it's basically what your calls to a Room Dao do -- if you have a
Dao
method that queries yourRoomDatabase
based on an id and returns aLiveData
, it will return a differentLiveData
instance based on the id.