管理来自不同rx.Observables

时间:2017-04-22 20:51:41

标签: android rx-java

按照讨论的主题here。我正在使用Clean Architecture编写Android应用程序。我有一个Interactor负责检索用户的Feed数据。流程是这样的:

  • 我必须从存储库中获取Feed数据,该存储库调用Retrofit的服务来执行API调用。
  • 如果出现问题,我将从内部使用Sqlite的FeedCache中获取Feed数据。
  • 我要将此Feed集合与另一个名为PendingPostCache的缓存中的另一组Feed合并。此缓存包含用户无法发布的所有文章(因为出现问题,没有互联网连接等)。

我的FeedCache和PendingPostCache都适用于Sqlite。如果出现问题,Botch可以抛出DBExceptions。对于服务器端发出请求的FeedRepository也可以在出现错误时抛出异常(ServerSideException)。

以下是我的Interactor的完整代码:

mFeedRepository.getFeed(offset, pageSize) //Get items from the server-side
                .onErrorResumeNext(mFeedCache.getFeed(userSipid)) //If something goes wrong take it from cache
                .mergeWith(mPendingPostCache.getAllPendingPostsAsFeedItems(user)) //Merge the response with the pending posts
                .subscribe(new DefaultSubscriber<List<BaseFeedItem>>() {
                    @Override
                    public void onNext(List<BaseFeedItem> baseFeedItems) {
                        callback.onFeedFetched(baseFeedItems);
                    }

                    @Override
                    public void onError(Throwable e) {
                        if (e instanceof ServerSideException) {
                            //Handle the http error
                        } else if (e instanceof DBException) {
                            //Handle the database cache error
                        } else {
                            //Handle generic error
                        }
                    }
                });

我不喜欢那些实例。我正在考虑创建一个自定义订阅者,称为MyAppSubscriber,它实现onError方法,进行那些实例比较,并执行一些名为onServerSideError(),onDBError()的方法。这样代码就会变得更清晰,我可以节省编写样板代码的实例。有人更好地了解如何处理这个问题?某种方法可以避免自定义订阅者?

1 个答案:

答案 0 :(得分:3)

只需使用构图:

public <T,E> Function<Throwable, Observable<T>> whenExceptionIs(Class<E> what, Function<E, Observable<T>> handler) {
  return t -> {
    return what.isInstance(t) ? handler.apply(what.cast(t)) : Observable.error(t);
  };
}

然后你正常使用它:

Observable.from(...).flatMap(...)
.onErrorResumeNext(whenExceptionIs(ServerSideException.class, e-> Observable.empty()))
.onErrorResumeNext(whenExceptionIs(DBException.class, e-> ...))

你甚至可以用一种方法抽象出所有这些:

public <T> Transformer<T, T> errorHandling() {
   return src -> src
      .onErrorResumeNext(whenExceptionIs(ServerSideException.class, e-> Observable.empty()))
      .onErrorResumeNext(whenExceptionIs(DBException.class, e-> ...));
}


Observable.from(...).flatMap(...)
.compose(errorHandling())
.subscribe();