在 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()
);
}
我正在思考如何将网络错误从数据层提升到视图层。
我将 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()
);
}