Обработка сетевой ошибки в 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));
                }
            }));

Как я могу испустить этот бросок?


person webo80    schedule 05.09.2017    source источник


Ответы (1)


Вы не связываете эти Observable здесь, поэтому ошибка из API Observable не будет распространяться вниз по потоку на уровень представления. (более того, я не уверен, как работает Room, но вы дважды запросите его для обновлений БД)

Если я правильно понимаю, db.dEventDataStore().getAll() создается Room, так что этот Flowable бесконечен, слушает изменения БД и испускает любые изменения. поэтому вы хотите запросить сервер, а в случае обновления данных БД и ожидать выброса из БД комнаты Flowable.

в этом случае вы можете сделать это параллельно, используя merge, а API, возможно, пропустить только ошибки, игнорируя любые элементы, которые он испускает. таким образом, в нисходящем направлении мы будем получать выбросы данных только из БД комнаты, но при этом получать уведомления об ошибках сервера.

 public Flowable<List<DEvent>> getAll() {
    return Flowable.merge(
            db.dEventDataStore().getAll(),
            dEventApi.getAll()
                    .doAfterSuccess(dEvents -> db.dEventDataStore().insertAll(dEvents))
                    .ignoreElement()
                    .toFlowable()
    );
}
person yosriz    schedule 06.09.2017
comment
Спасибо! Работал, как и ожидалось, возвращая xxxAPIDataSource (модифицированный) Flowable. - person webo80; 06.09.2017