RxJava watchOn似乎无法正常工作

时间:2020-05-09 15:27:56

标签: android multithreading rx-java2

我正面临来自RxJava的错误

Android“只有创建视图层次结构的原始线程才能触摸其视图。”

我使用的代码

Log.d(TAG, "stratObserving:qw ${Thread.currentThread()}")
(application as? App)?.relayPages
                ?.doAfterNext{
                    hideLoading()
                }
                ?.observeOn(AndroidSchedulers.mainThread())
                ?.subscribe({
                   "data found ${it.size}".log()
                    pageAdapter.setPageList(it)
                    rvAyahsPages.scrollToPosition(pos)
                    "data pageAdapter ${pageAdapter.itemCount} , ${Thread.currentThread()}".log()
                    foundState()
                }, {
                    "error ${it.message}".log()
                })
                ?.addTo(model.bg)
 private fun foundState() {
        spShowAyahs?.visibility = View.GONE
        tvNoQuranData?.visibility = View.GONE
        rvAyahsPages?.visibility = View.VISIBLE
        "found $rvAyahsPages $spShowAyahs".log()
    }

但是

Log.d(TAG, "stratObserving:qw ${Thread.currentThread()}") 打印 Thread [main,5,main]

Log.d(TAG, "stratObserving:qw ${Thread.currentThread()}") 打印 Thread [main,5,main]

[注意]

此问题不同于“ Android“只有创建视图层次结构的原始线程才能触摸其视图。””回答该解决方案应在MainThread上运行,但实际上它在MainThread上运行

[编辑] 问题是操作员的命令,所以 将 doAfterNext 替换为 observeOn

1 个答案:

答案 0 :(得分:0)

正如@fraggjkee和@EpicPandaForce已经提到的,问题出在这里:

(application as? App)?.relayPages
                ?.doAfterNext{
                    hideLoading()
                }

有什么问题: Android“只有创建视图层次结构的原始线程才能触摸其视图

当有人尝试从非UI线程更新UI状态时,会引发此问题。 UI-eventloop是单线程的。因此,禁止其他线程更新UI状态(例如,视图属性等)

为什么observeOn不起作用?

(application as? App)?.relayPages
                ?.doAfterNext{
                    hideLoading()
                }
                ?.observeOn(AndroidSchedulers.mainThread())

ObserveOn在可观察范围内将线程从一个运算符切换到另一个运算符。当relayPages发出一个值时,它将在任何给定线程(最有可能是订阅线程)上通过doAfterNext。通过doAfterNext之后,许可将通过ObserveOn-operator。这是魔术发生的地方。在此运算符中,emit(onNext)操作将作为可运行程序放入UI事件循环(AndroidSchedulers#mainThread)中。

有关更多说明,请查看以下说明:http://tomstechnicalblog.blogspot.de/2016/02/rxjava-understanding-observeon-and.html

问题

从非UI线程调用#doAfterNext运算符,该非UI线程尝试更改某些UI状态。

分辨率

所有UI状态更改都必须从UI线程调用。因此,必须确保是这种情况。

(application as? App)?.relayPages
                // observeOn switches the thread from X to the UI-eventloop
                ?.observeOn(AndroidSchedulers.mainThread())
                // hideLoading is called from UI-eventloop, everything should be fine
                ?.doAfterNext{
                    hideLoading()
                }

摘要

在更改UI状态之前,ObserveOn必须放置在操作员链中。

相关问题