android - RxJava : getting "Only the original thread that created a view hierarchy can touch its views" even after subscribing on main thread

标签 android rx-java2

我在自动完成 TextView 上使用扩展函数来使用去抖动策略并在主线程上订阅。

 binding.autoCompleteTextView2.addRxTextWatcher()
         .observeOn(AndroidSchedulers.mainThread())
         .subscribeOn(AndroidSchedulers.mainThread())
         .debounce(400, TimeUnit.MILLISECONDS)
         .subscribe {
            if (!TextUtils.isEmpty(it)) {
                        viewModel.searchTeacher(viewModel.meditationDetails?.schoolId,it)
                        binding?.etEmailOfTeacher?.visible()   //Crash at this point
                        binding?.tvEmailOfYourTeacher?.visible()
                }
       }

扩展功能:-

fun EditText.addRxTextWatcher(): Observable<String?> {
val flowable = Observable.create<String?> {
    addTextChangedListener(object : TextWatcher {
        override fun afterTextChanged(s: Editable?) {
        }

        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
            it.onNext(s?.toString())
        }

        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
        }
    })
}

当我尝试更新“只有创建 View 层次结构的原始线程才能触及它的 View ”的 View 可见性时,我遇到了崩溃。但我已经订阅并观察了 mainThread 。我在这里做错了什么?

完整日志:

2019-09-27 11:51:06.878 9490-9575/com.example.example E/ACRA: ACRA caught a CalledFromWrongThreadException for com.example.example
    android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
        at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:7959)
        at android.view.ViewRootImpl.focusableViewAvailable(ViewRootImpl.java:3866)
        at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:917)
        at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:917)
        at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:917)
        at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:917)
        at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:917)
        at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:917)
        at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:917)
        at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:917)
        at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:917)
        at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:917)
        at android.view.View.setFlags(View.java:14121)
        at android.view.View.setVisibility(View.java:10007)
        at in.eightfolds.utils.ExtentionFunctionsKt.visible(ExtentionFunctions.kt:345)
        at com.example.example.fragment.OnBordingCreateMeditationAdditionalDetailsFragment$setAutoCompleteTextView2$2.accept(OnBordingCreateMeditationAdditionalDetailsFragment.kt:283)
        at com.example.example.fragment.OnBordingCreateMeditationAdditionalDetailsFragment$setAutoCompleteTextView2$2.accept(OnBordingCreateMeditationAdditionalDetailsFragment.kt:38)
        at io.reactivex.internal.observers.LambdaObserver.onNext(LambdaObserver.java:59)
        at io.reactivex.observers.SerializedObserver.onNext(SerializedObserver.java:111)
        at io.reactivex.internal.operators.observable.ObservableDebounceTimed$DebounceTimedObserver.emit(ObservableDebounceTimed.java:142)
        at io.reactivex.internal.operators.observable.ObservableDebounceTimed$DebounceEmitter.run(ObservableDebounceTimed.java:167)
        at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:59)
        at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:51)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:764)

如果我在 activity?.runOnUiThread{} 中写入可见性,那么它工作正常。那么为什么即使我在 mainthread 上订阅了也会出现异常?

最佳答案

debounce 运算符将订阅计算调度程序。像这样重新排序您的函数:

binding.autoCompleteTextView2.addRxTextWatcher() <-- text watch is on the main thread
         .debounce(400, TimeUnit.MILLISECONDS) <-- debounced throw the result on Computation Scheduler
         .observeOn(AndroidSchedulers.mainThread()) <-- ObserveOn throw the result on MainThread
         .subscribe {
            if (!TextUtils.isEmpty(it)) {
                        viewModel.searchTeacher(viewModel.meditationDetails?.schoolId,it)
                        binding?.etEmailOfTeacher?.visible()   //Crash at this point
                        binding?.tvEmailOfYourTeacher?.visible()
                }
       }

引用:RxJava Debounce doc

debounce(long, TimeUnit) is by default on the computation Scheduler

好处:您可以在每次操作后使用运算符 doOnNext 并记录哪个线程与 Thread.currentThread().getName()

一起使用

例如:

...
.debounce(...)
.doOnNext{ Log.d(TAG, "Debounce on: " +  Thread.currentThread().getName()) } <-- This will show RxComputationScheduler-N
.observeOn(AndroidSchedulers.mainThread())
.doOnNext{ Log.d(TAG, "Debounce on: " +  Thread.currentThread().getName()) } <-- This will show main
...

关于android - RxJava : getting "Only the original thread that created a view hierarchy can touch its views" even after subscribing on main thread,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58129221/

相关文章:

android - 防止代码意外进入生产

java - 如何在我的代码中使用 SwitchMap (RXJAVA)?

java - Android - 将 RxJava 与 Retrofit 一起使用会导致 IllegalArgumentException

android - 耳机和扬声器同时输出音频

android - 使用 Rxjava 2 和 Retrofit 2 加载数据失败时应用程序崩溃

android - 使用 LiveDataReactiveStreams 时如何从 Rxjava Flowable 返回错误?

kotlin - livedata postvalue是否需要observeOn?

android - 获取微调器的名称值

android - 如何在android中将xml数据发布到服务器

android - 指定Android客户端的Socket事件