Reputation: 6560
I'm using RxJava, Room and Retrofit to accomplish Repository pattern in Android. Everything is working except this one thing. I have implemented SearchView
for searching data. Now when search view text changes I call search method. here is how it looks like
mLocal.searchMovies(query) //returns Single
mRemote.searchMovies(query) //returns Single
public Single<List<MovieEntity>> search(String query) {
return mLocal.searchMovies(query)
.toMaybe()
.switchIfEmpty(mRemote.searchMovies(query)
.map(data -> {
mLocal.saveAll(data);
return data;
}));
}
mLocal
queries the room database and mRemote
calls retrofit to fetch data from REST API. The problem is, this only calls mLocal and when room returns empty row network call is not initiated. I have tried everything I possibly and read many articles but I cannot understand how to get it work.
Each of mLocal and mRemote works fine. Only chaining them does not accomplish what I want.
Upvotes: 0
Views: 1644
Reputation: 25573
Your chain does not work because .toMaybe()
from Single
cannot produce Maybe.empty()
, which is the result required to have .switchIfEmpty
take effect.
You will either need to replace it with Single.onErrorResume
so the error condition from a missing entry results in the remote query, or make it return Maybe
to accurately represent the tristate of <Result,NotCached,Error>
.
Upvotes: 1
Reputation: 6560
The explanation of my problem is the same as in this answer. I will copy relevant part and post my working piece of code after applying it.
Note: I changed to Flowable from Single/MayBe. am not sure how much it affects the original code, hadn't I changed the type of Observables.
Based on the OP's feedback, the allDatas source was infinite but returned an empty List. The resolution was to apply at least take(1) to get exactly one response from allDatas and then optionally filter out the empty List so switchIfEmpty can switch over to the alternatives
public Flowable<List<MovieEntity>> getMovies() {
return mLocal.allMovies().take(1)
.filter(list -> !list.isEmpty())
.switchIfEmpty(mRemote.allMovies()
.doOnNext(data -> mLocal.saveAll(data))
);
}
Upvotes: 0