我使用Room with RxJava2通过Repository Pattern原则实现我的数据层。
我有以下简单的代码来决定从哪里选择数据。
@Override
public Single<Team> getTeamById(int teamId) {
return Single.
concat(local.getTeamById(teamId),
remote.getTeamById(teamId)).
filter(team -> team != null).
firstOrError();
}
这里的问题是,如果数据不可用,它不会转到远程源,而是从第一个源(本地)返回错误。
android.arch.persistence.room.EmptyResultSetException: Query returned empty result set: select * from teams where id = ?
我应该如何指示concat放弃收到的任何错误并继续连接?
答案 0 :(得分:2)
如果你不确定你是否能从你的数据提供者那里收到至少一个团队,你应该考虑使用Maybe而不是Single。
您可以在此处查找定义:
Single表示:
它总是发出一个值或错误通知
使用Maybe代替: Maybe
可能有0或1项或某些反应信号表示错误 源
由于您的错误已经指出,从查询中提取结果时似乎存在问题。
正确处理结果提取,以便在尝试提取结果之前检查是否有结果。因此,如果没有找到Team,则Maybe会返回0或1项,并且不会抛出任何错误。
答案 1 :(得分:2)
您无法在RxJava2中传递null。因此,只要您的本地仓库为空,您就无法在单个仓库中返回null。关于处理空对象的问题有一个问题:Handle null in RxJava2
此外,您还可以找到一篇文章,展示使用RxJava2优先保存存储库模式: https://android.jlelse.eu/rxjava-2-single-concat-sample-for-repository-pattern-1873c456227a
如此简化 - 而不是从本地和远程repo返回null传递某种&#34;空&#34;宾语。这对您的商务逻辑也很有用,可以让您识别空数据集。
答案 2 :(得分:1)
我使用Maybe
来解决我的Rxjava2
存储库模式问题。
在您的情况下,我会使用以下代码对其进行排序:
//you may need to rewrite your local.getTeamById method
protected Maybe<Team> getTeamById(int teamId) {
Team team = localDataHelper.getTeamById(teamId);
return team != null ? Maybe.just(team) : Maybe.empty();
}
@Override
public Single<Team> getTeamById(int teamId) {
Maybe<Team> cacheObservable = local.getTeamById(teamId);
Maybe<Team> apiCallObservable = remote.getTeamById(teamId).toMaybe();
return Maybe.concat(cacheObservable, apiCallObservable)
.toSingle();
}
答案 3 :(得分:0)
如果您想在第一个来源错误时继续(而不是填空),则可以使用onErrorResumeNext
代替concat
(我假设两个来电都返回Observable
,调整必要时):
return local.getTeamById(teamId)
.onErrorResumeNext(error -> {
if (error instanceof EmptyResultSetException) {
return remote.getTeamById(teamId));
}
return Observable.error(error);
})
.firstOrError();