使用 RxAndroid 线程切换问题

最近在学 RxAndroid,按照设计,RxAndroid 是可以方便地切换线程,接着更新UI必须在 main 线程,但是我使用 RxAndroid 切换线程的时候,即使不再 main 线程上也可以更新 UI,请问是什么原因?

minSdkVersion 21
targetSdkVersion 25

compile 'io.reactivex.rxjava2:rxjava:2.1.1'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'

代码如下:


    private void rxAndroidThread() {

        Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(@NonNull ObservableEmitter<String> e) throws Exception {
                Log.i(TAG, "subscribe: Thread is " + Thread.currentThread().getName());
                e.onNext("Hello ");
                e.onNext("World!!!");
                e.onComplete();
            }
        })
                .subscribeOn(Schedulers.io())
                .observeOn(Schedulers.newThread())
                .subscribe(new Consumer<String>() {
                    @Override
                    public void accept(@NonNull String s) throws Exception {
                        Log.i(TAG, "accept: Thread is " + Thread.currentThread().getName());
                        btn.setText(s);
                    }
                });

    }

Log 如下:

07-05 15:59:45.058 23781-23781/exp.rusan.rxandroidsample I/MAIN_ACTIVITY: onCreate: Thread:  main
07-05 15:59:45.202 23781-23845/exp.rusan.rxandroidsample I/MAIN_ACTIVITY: subscribe: Thread is RxCachedThreadScheduler-1
07-05 15:59:45.205 23781-23846/exp.rusan.rxandroidsample I/MAIN_ACTIVITY: accept: Thread is RxNewThreadScheduler-1
07-05 15:59:45.205 23781-23846/exp.rusan.rxandroidsample I/MAIN_ACTIVITY: accept: Thread is RxNewThreadScheduler-1

运行图:
图片说明

续上:
而当我加上

Thread.sleep(1000);

时,程序就会发生错误。

  public void accept(@NonNull String s) throws Exception {
                        Thread.sleep(1000);

                        Log.i(TAG, "accept: Thread is " + Thread.currentThread().getName());
                        btnStart.setText(s);
                    }

Log:

07-07 11:28:29.852 9572-9644/exp.rusan.rxandroidsample E/AndroidRuntime: FATAL EXCEPTION: RxNewThreadScheduler-1
                                                                         Process: exp.rusan.rxandroidsample, PID: 9572
                                                                         io.reactivex.exceptions.OnErrorNotImplementedException: Only the original thread that created a view hierarchy can touch its views.
                                                                             at io.reactivex.internal.functions.Functions$OnErrorMissingConsumer.accept(Functions.java:704)
                                                                             at io.reactivex.internal.functions.Functions$OnErrorMissingConsumer.accept(Functions.java:701)
                                                                             at io.reactivex.internal.observers.LambdaObserver.onError(LambdaObserver.java:74)
                                                                             at io.reactivex.internal.observers.LambdaObserver.onNext(LambdaObserver.java:64)
                                                                             at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.drainNormal(ObservableObserveOn.java:200)
                                                                             at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.run(ObservableObserveOn.java:252)
                                                                             at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:61)
                                                                             at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:52)
                                                                             at java.util.concurrent.FutureTask.run(FutureTask.java:237)
                                                                             at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:272)
                                                                             at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
                                                                             at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
                                                                             at java.lang.Thread.run(Thread.java:761)
                                                                          Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
                                                                             at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6898)
                                                                             at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:1048)
                                                                             at android.view.View.requestLayout(View.java:19785)
                                                                             at android.view.View.requestLayout(View.java:19785)
                                                                             at android.view.View.requestLayout(View.java:19785)
                                                                             at android.view.View.requestLayout(View.java:19785)
                                                                             at android.view.View.requestLayout(View.java:19785)
                                                                             at android.view.View.requestLayout(View.java:19785)
                                                                             at android.view.View.requestLayout(View.java:19785)
                                                                             at android.widget.TextView.checkForRelayout(TextView.java:7368)
                                                                             at android.widget.TextView.setText(TextView.java:4480)
                                                                             at android.widget.TextView.setText(TextView.java:4337)
                                                                             at android.widget.TextView.setText(TextView.java:4312)
                                                                             at exp.rusan.rxandroidsample.MainActivity$9.accept(MainActivity.java:293)
                                                                             at exp.rusan.rxandroidsample.MainActivity$9.accept(MainActivity.java:287)
                                                                             at io.reactivex.internal.observers.LambdaObserver.onNext(LambdaObserver.java:60)
                                                                             at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.drainNormal(ObservableObserveOn.java:200) 
                                                                             at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.run(ObservableObserveOn.java:252) 
                                                                             at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:61) 
                                                                             at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:52) 
                                                                             at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
                                                                             at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:272) 
                                                                             at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 
                                                                             at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 
                                                                             at java.lang.Thread.run(Thread.java:761)