RxJava observeOn 似乎无法正常工作

RxJava observeOn seems to be not work correctly

我正面临来自 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 “Only the original thread that created a view hierarchy can touch its views.”" 的答案,解决方案是 运行 在 MainThread 上,但这里实际上是 运行 在 MainThread

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

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

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

What is the problem: Android “Only the original thread that created a view hierarchy can touch its views

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

Why is observeOn not working?

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

ObserveOn 在 observable 中将线程从一个运算符切换到另一个运算符。当 relayPages 发出一个值时,它将在任何给定线程上通过 doAfterNext 传递,很可能是订阅线程。通过 doAfterNext 之后,退出将通过 ObserveOn 操作符。这就是魔法发生的地方。在此运算符中,emit (onNext) 操作将在 UI-eventloop (AndroidSchedulers#mainThread).

中作为可运行项排队。

如需进一步说明,请查看此说明:http://tomstechnicalblog.blogspot.de/2016/02/rxjava-understanding-observeon-and.html

Problem

#doAfterNext 运算符是从非 UI 线程调用的,它试图更改某些 UI 状态。

Resolution

所有 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()
                }

Summary

ObserveOn 必须放在运算符链中,在 UI 状态更改之前。