RxJava2 с обработкой ошибок комнаты - исключение основного потока базы данных - PullRequest
0 голосов
/ 26 октября 2018

Я пытаюсь получить элементы из удаленного источника, если это не сработает (без интернета), я бы хотел получить кэшированные элементы из базы данных комнаты.Я создал новый сингл для случая, когда произошла ошибка, и я указал, на какой поток он должен подписаться и наблюдать.Я по-прежнему это исключение, хотя:

java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.

Это метод для извлечения элементов:

public LiveData<List<Article>> getNewsArticles() {
    return LiveDataReactiveStreams.fromPublisher(
            newsService.getNewsArticles()
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())

                    .onErrorResumeNext(throwable ->
                            Single.just(newsDao.findAllForNumber(AMOUNT_OF_ARTICLES_PER_PAGE))
                                    .subscribeOn(Schedulers.io())
                                    .observeOn(AndroidSchedulers.mainThread()))

                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())

                    .doOnSuccess(newsArticles -> Completable.fromAction(() ->
                            newsDao.insertAll(newsArticles))
                            .subscribeOn(Schedulers.io()))
                    .toFlowable());
}

LiveDataReactiveStreams преобразует его в объект liveata и обрабатывает подписку, так что мое представление знает толькоо livingata.

Я просто не могу заставить вызов onErrorResumeNext работать в фоновом потоке.

Любая помощь будет принята с благодарностью!

ОТВЕТ

Я решил проблему с помощью следующего кода:

public LiveData<List<Article>> getNewsArticles() {
    return LiveDataReactiveStreams.fromPublisher(
            newsService.getNewsArticles()
                    .observeOn(Schedulers.io())
                    .doOnSuccess(newsArticles -> newsDao.insertAll(newsArticles))
                    .onErrorResumeNext(throwable -> Single.fromCallable(() -> newsDao.findAllForNumber(AMOUNT_OF_ARTICLES_PER_PAGE)))
                    .toFlowable());
}

1 Ответ

0 голосов
/ 26 октября 2018

В методе RxJava subscribeOn укажите планировщик, на котором будет работать Observable.Но метод наблюдений на указывает планировщик, на котором наблюдатель будет наблюдать эту наблюдаемую.

Для простых:

Single
.zip(observable1.getList(), observable2.getAnotherList()) // Simple zip for example
.observeOn(AndroidSchedulers.mainThread()) // switch to main thread
.map(mapper.map(list1, list2)) // this command will execute on main thread
.observeOn(Schedulers.io()) // switch to io thread
.map(anotherMapper.map(complexList)) // this command will execute on io thread
.observeOn(AndroidSchedulers.mainThread()) // switch to main thread
.subscribeOn(Schedulers.io()) // specify thread for zip command

ObserveOn работает только в нисходящем направлении.Все методы после наблюдения были перемещены в поток ввода-вывода.В то время как методы, предшествующие наблюдаемому, все еще находятся в главном потоке.

В вашем примере вы где-то пытаетесь вызвать команду room dao в главном потоке, и система не позволяет выполнить в основном потоке.Вы можете установить точку останова для каждой команды, тогда в IDE посмотрите точно имя потока, где будет выполняться команда.

Более сложные примеры см. В этой статье .

...