RxJava2 Single.Concat用于存储库模式

时间:2018-03-18 11:35:34

标签: android repository-pattern rx-java2

我使用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放弃收到的任何错误并继续连接?

4 个答案:

答案 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();