RxJava observeOn失效引发Android视图线程错误排查求助
Hey there, I’ve run into this tricky RxAndroid quirk before—you check your logs and confirm you’re on the main thread, but that annoying view thread error still pops up. Let’s break down what’s going on here and fix it for good.
The Problem You’re Facing
You’re getting this familiar error message:
Only the original thread that created a view hierarchy can touch its views.
Your code looks like this, and logs show Thread [main,5,main] in the subscribe block—so you’re confused why the error persists:
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() }
The Hidden Culprit: Operator Order
Here’s the key mistake: your doAfterNext is running on the wrong thread.
In RxJava, observeOn(AndroidSchedulers.mainThread()) only affects operators that come after it in the chain. Since you placed doAfterNext before observeOn, the hideLoading() call inside it is executing on whatever thread relayPages emits from—not the main thread. Your subscribe block is correctly on the main thread (hence the log), but the doAfterNext step is slipping through and touching views off the main thread, triggering the error.
The Simple Fix: Swap Operator Order
Just move observeOn to before doAfterNext, so every downstream operation runs on the main thread:
Log.d(TAG, "stratObserving:qw ${Thread.currentThread()}") (application as? App)?.relayPages ?.observeOn(AndroidSchedulers.mainThread()) // Switch to main thread first ?.doAfterNext{ hideLoading() } // Now this runs safely on main thread ?.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)
With this reordering, doAfterNext, the subscribe block, and all view-related calls (like hideLoading() and foundState()) will execute on the main thread—exactly where they need to be to avoid the thread error.
Quick RxJava Threading Reminder
observeOncontrols the thread for all downstream operators (everything after it in the chain).- Always double-check operator order when dealing with thread-sensitive work like updating views—it’s easy to mix up and cause silent thread issues!
内容的提问来源于stack exchange,提问作者Mahmoud Mabrok

