Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use switchIfEmpty RxJava

The logic here is that if the ratings in the database are empty, then I want to get them from the API. I have the following code:

Observable.from(settingsRatingRepository.getRatingsFromDB())
            .toList()
            .switchIfEmpty(settingsRatingRepository.getSettingsRatingModulesFromAPI())
            .compose(schedulerProvider.getSchedulers())
            .subscribe(ratingsList -> {
                view.loadRatingLevels(ratingsList, hideLocks);
            }, this::handleError);

The getRatingsFromDB() call returns List<SettingRating>, but the API call returns Observable<List<SettingRating>>.

However, when I unit test this, when I pass an empty list from the database call, it does not execute the API call. Can someone pls help me in this matter. This is my unit test code:

when(mockSettingsRatingsRepository.getRatingsFromDB()).thenReturn(Collections.emptyList());
List<SettingsRating> settingsRatings = MockContentHelper.letRepositoryReturnSettingsRatingsFromApi(mockSettingsRatingsRepository);

settingsParentalPresenter.onViewLoad(false);

verify(mockView).loadRatingLevels(settingsRatings, false);
like image 623
blackpanther Avatar asked Aug 22 '16 11:08

blackpanther


3 Answers

As @Kiskae mentioned, it's the fact that I am confusing an empty list with an empty Observable. Therefore, I have used the following which is what I want:

public void onViewLoad(boolean hideLocks) {
    Observable.just(settingsRatingRepository.getRatingsFromDB())
            .flatMap(settingsRatings -> {
                if (settingsRatings.isEmpty()) {
                    return settingsRatingRepository.getSettingsRatingModules();
                } else {
                    return Observable.just(settingsRatings);
                }
            })
            .compose(schedulerProvider.getSchedulers())
            .subscribe(ratingsList -> {
                view.loadRatingLevels(ratingsList, hideLocks);
            }, this::handleError);
}
like image 69
blackpanther Avatar answered Nov 05 '22 11:11

blackpanther


Observable#toList() returns a single element. If the observable from which it gets its elements is empty, it will emit an empty list. So by definition the observable will never be empty after calling toList().

like image 26
Kiskae Avatar answered Nov 05 '22 12:11

Kiskae


switchIfEmpty will only be called when your observer completes without emitting any items. Since you are doing toList it will emit list object. Thats why your switchIfEmpty is never getting called.

If you want to get data from cache and fallback to your api if cache is empty, use concat along with first or takeFirst operator.

For example:

Observable.concat(getDataFromCache(), getDataFromApi())
            .first(dataList -> !dataList.isEmpty());
like image 3
Kalpesh Patel Avatar answered Nov 05 '22 12:11

Kalpesh Patel