簡體   English   中英

具有Room錯誤處理的RxJava2-數據庫主線程異常

[英]RxJava2 with Room error handling - Database main thread exception

我正在嘗試從遠程源檢索項目,如果這不起作用(沒有互聯網),我想從會議室數據庫中檢索緩存的項目。 我為錯誤發生的時間創建了一個新的單曲,並指定了應該訂閱和觀察的線程。 我還是這個例外:

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其轉換成livedata對象和處理訂閱新資料,所以我的觀點只知道livedata。

我只是似乎無法使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());
}

在RxJava方法subscribeOn指定在其上可觀察到的將操作的調度器。 但是方法observeOn指定了調度程序,觀察者將在該調度程序上觀察此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僅在下游起作用。 beforeOn之后的所有方法均已移至IO線程。 而watchOn之前的方法仍在主線程中。

在您的示例中,您嘗試在主線程上調用room dao命令,並且系統不允許在主線程上執行。 您可以在每個命令上設置斷點,然后在IDE中准確查找要執行命令的線程名稱。

有關更復雜的示例,請參見本文

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM