在 Retrofit + RxJava2 + Room 上处理网络错误

Handle network error on Retrofit + RxJava2 + Room

我正在思考如何将网络错误从数据层提升到视图层。

我将 Room 与 RxJava2 和 Retrofit2 一起使用。我将存储库模式实现为本地优先,因此我查询本地数据,同时从远程获取数据,并在必要时更新本地数据。在代码中,这将是:

public Flowable<List<DEvent>> getAll() {
    return db.dEventDataStore().getAll()
        .doOnSubscribe(new Consumer<Subscription>() {
            @Override
            public void accept(final Subscription subscription) throws Exception {
                dEventApi.getAll().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new MaybeObserver<List<DEvent>>() {
                        @Override
                        public void onSubscribe(@NonNull Disposable disposable) {
                            Timber.d("Remote onSubscribe");
                        }

                        @Override
                        public void onSuccess(@NonNull List<DEvent> dEvents) {
                            Timber.d("Remote onSuccess!");
                            db.dEventDataStore().insertAll(dEvents);
                        }

                        @Override
                        public void onError(@NonNull Throwable throwable) {
                            Timber.d("Remote onError!");
                        }

                        @Override
                        public void onComplete() {
                            Timber.d("Remote onComplete!");
                        }
                    }
                );
            }
        });
}

并且在视图层中:

    mDisposable.add(repo.getAll()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Consumer<List<DEvent>>() {
                @Override
                public void accept(List<DEvent> dEvents) throws Exception {
                    Timber.d("OnNext!!");
                    mView.showEvents(dEvents);
                }
            }, new Consumer<Throwable>() {
                @Override
                public void accept(Throwable throwable) throws Exception {
                    Timber.e("Error on getting DEvents - " + Log.getStackTraceString(throwable));
                }
            }));

我怎样才能发出那个 throwable?

您没有在此处链接这些 Observable - 因此来自 API Observable 的错误不会向下传播到视图层。 (此外,我不确定 Room 是如何运行的,但您将查询它两次以获取数据库更新)

如果我理解正确,db.dEventDataStore().getAll() 由 Room 创建,所以这个 Flowable 是无限的,监听数据库变化并发出任何变化。所以你想查询服务器,并且在数据更新数据库的情况下并期望从 Room 的 DB Flowable 发出。

在这种情况下,您可以使用 merge 并行执行此操作,并且 API 也许,通过忽略它发出的任何元素来仅传递错误。通过这种方式,下游我们将仅从 Room DB 获取数据排放,同时仍会收到服务器错误通知。

 public Flowable<List<DEvent>> getAll() {
    return Flowable.merge(
            db.dEventDataStore().getAll(),
            dEventApi.getAll()
                    .doAfterSuccess(dEvents -> db.dEventDataStore().insertAll(dEvents))
                    .ignoreElement()
                    .toFlowable()
    );
}