这里的逻辑是,如果数据库中的评级为空,那么我想从API中获取它们。我有以下代码:
Observable.from(settingsRatingRepository.getRatingsFromDB())
.toList()
.switchIfEmpty(settingsRatingRepository.getSettingsRatingModulesFromAPI())
.compose(schedulerProvider.getSchedulers())
.subscribe(ratingsList -> {
view.loadRatingLevels(ratingsList, hideLocks);
}, this::handleError);
getRatingsFromDB()
调用返回List<SettingRating>
,但API调用返回Observable<List<SettingRating>>
。
但是,当我对它进行单元测试时,当我从数据库调用中传递一个空列表时,它不会执行API调用。有人可以帮我解决这个问题。这是我的单元测试代码:
when(mockSettingsRatingsRepository.getRatingsFromDB()).thenReturn(Collections.emptyList());
List<SettingsRating> settingsRatings = MockContentHelper.letRepositoryReturnSettingsRatingsFromApi(mockSettingsRatingsRepository);
settingsParentalPresenter.onViewLoad(false);
verify(mockView).loadRatingLevels(settingsRatings, false);
答案 0 :(得分:6)
正如@Kiskae所提到的那样,事实是我将空列表与空Observable混淆。因此,我使用了以下我想要的东西:
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);
}
答案 1 :(得分:1)
Observable#toList()
返回单个元素。如果获取其元素的observable为空,则它将发出一个空列表。因此,根据定义,在调用toList()
后,observable将永远不会为空。
答案 2 :(得分:1)
switchIfEmpty
只有在您的观察者完成而不发出任何物品时才会被调用。
由于您正在执行toList
,它将发出列表对象。这就是为什么你的switchIfEmpty
永远不会被召唤的原因。
如果要在缓存为空时从缓存中获取数据并回退到api,请使用concate
以及first
或takeFirst
运算符。
例如:
Observable.concat(getDataFromCache(), getDataFromApi())
.first(dataList -> !dataList.isEmpty());
答案 3 :(得分:0)
根据@kiskae的回答,您使用toList()
会将汇总的元素作为单个List
发出。
此处可以使用Observable.just()
+ a flatMap
替代。
Observable.from
将遍历您的服务返回的列表并发出每个单独的项目,因此Observable<Rating>
。Observable
。如果所述列表为空,则自然会产生空Observable<Rating>
。您的API调用也会产生List<Rating>
,在这两种情况下,您都希望将其重新聚合回toList()
以进行进一步处理。
在switchIfEmpty
调用API之后,只需将原始代码中的Observable.from(settingsRatingRepository.getRatingsFromDB())
.switchIfEmpty(settingsRatingRepository.getSettingsRatingModulesFromAPI())
.toList()
.compose(schedulerProvider.getSchedulers())
.subscribe(ratingsList -> {
view.loadRatingLevels(ratingsList, hideLocks);
}, this::handleError);
向下移动一行:
List
当然,该解决方案可能会产生更多垃圾(因为数据库Observable
变成了List
只是为了稍后变成新的failed()