最近在学 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)