It seems NetworkBoundResource works on the bases that, the data is stored in the DB. I have data I want to fetch from an API, however this data won't be stored in the DB as it does not need to live longer than the users session on the activity lifecycle. How could we still use NetworkBoundResource in this case?
To answer my own question, what I have come up with is to build a cache class, that the repository also knows about and in cases where I dont need data saved to the DB, I store it in the cache. The cache class returns the data using LiveData signals and this works well with the NetworkBoundResource methods.
If there is a better way of doing this, I would love to hear it.
If you don't have to cache, you don't need it at all. I used the service directly in the repository and it worked seamlessly.
That sounds great. Could you give me an example if possible? Would really appreciate! Thanks
Of course. I will use UserRepository for simplicity's sake. In loadUser(String login), Notice this method returns LiveData<Resource<User>>, and GithubSerivce#getUser() returns LiveData<ApiResponse<User>>, which is very similiar, I removed the Resource wrapper and made the both methods returns LiveData<ApiResponse<List<Repo>>>.
Consequently, the UserRepository#getuser(String login) became like this. and that doesn't affect UserViewModel or LiveDataCallAdapter
public LiveData<Resource<User>> loadUser(String login) {
return githubService.getUser(login);
}
So, what I did is totally removing NetworkBoundResource, some might have objection for that, cuz Resource<T> can handle some network errors. So, I change the ApiResponse<T> to handle some errors.
public final class ApiResponse<V> {
@Nullable
private final V data;
@Nullable
private final Throwable error;
/**
* In Case of successful API request, pass the received data here.
*
* @param Data received data from successful API Call.
*/
public ApiResponse(@NonNull final V Data) {
Objects.requireNonNull(Data);
this.data = Data;
this.error = null;
}
/**
* In case of failed API request, pass error.
* @param error The cause of the failed API Call.
*/
public ApiResponse(@NonNull final Throwable error) {
Objects.requireNonNull(error);
this.error = error;
this.data = null;
}
public boolean isSuccessful() {
return data != null && error == null;
}
@NonNull
public V getData() {
if (data == null) {
throw new IllegalStateException("Data is null; Call ApiResponse#isSuccessful() first.");
}
return data;
}
@NonNull
public Throwable getError() {
if (error == null) {
throw new IllegalStateException("error is null; Call ApiResponse#isSuccessful() first.");
}
return error;
}
}
ApiResponse<V> either has data or error and more simple.
However, if you want to keep the Resource<T> wrapper, the turn around for that is editing NetworkBoundResource and change the logic by removing db related actions and shouldFetch() will be always true, BUT I guess NetworkBoundResource became useless and more complex.
@amrro Thanks for the sample and explanation. This does indeed look like a good solution. However, in some cases, I need the Repo to decide, if it should fetch from a DB or from the network. I think in my case, I might need to keep NetworkBoundResource. I will try implement some of your recommendations though.
@amrro and @RJ-Clegg Can you tell me how to add loader if i don't want to use NetworkBoundResource ?
Most helpful comment
Of course. I will use
UserRepositoryfor simplicity's sake. InloadUser(String login), Notice this method returnsLiveData<Resource<User>>, andGithubSerivce#getUser()returnsLiveData<ApiResponse<User>>, which is very similiar, I removed the Resource wrapper and made the both methods returnsLiveData<ApiResponse<List<Repo>>>.Consequently, the
UserRepository#getuser(String login)became like this. and that doesn't affectUserViewModelorLiveDataCallAdapterSo, what I did is totally removing
NetworkBoundResource, some might have objection for that, cuzResource<T>can handle some network errors. So, I change theApiResponse<T>to handle some errors.ApiResponse<V>either has data or error and more simple.However, if you want to keep the
Resource<T>wrapper, the turn around for that is editingNetworkBoundResourceand change the logic by removing db related actions andshouldFetch()will be always true, BUT I guessNetworkBoundResourcebecame useless and more complex.