在上一篇文章RxJava2笔记(三、订阅线程切换)中,我们分析了订阅线程是如何切换的,即调用subscribeOn()来切换订阅线程时都执行了哪些操作。在本文我们将继续介绍观察者线程切换,也就是将线程由子线程切换回UI线程。
继续在前面的基础上修改代码,在订阅线程切换方法后调用observeOn(AndroidSchedulers.mainThread())将线程切换回主线程:
Observable.create(new ObservableOnSubscribe() {
@Override
public void subscribe(ObservableEmitter emitter) {
Log.i(TAG, "subscribe--运行线程:" + Thread.currentThread().getName());
emitter.onNext(1);
emitter.onNext(2);
try {
TimeUnit.MILLISECONDS.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
emitter.onNext(3);
emitter.onComplete();
}
})
//将线程由UI线程切换到子线程执行IO请求
.subscribeOn(Schedulers.io())
//将线程切换回UI线程,方面后续操作更新UI界面
.observeOn(AndroidSchedulers.mainThread())
.subscribe(observer);
看下运行结果:
I/MainActivity: onSubscribe--运行线程:main
I/MainActivity: subscribe--运行线程:RxCachedThreadScheduler-1
I/MainActivity: onNext: 1 --运行线程:main
I/MainActivity: onNext: 2 --运行线程:main
I/MainActivity: onNext: 3 --运行线程:main
I/MainActivity: onComplete--运行线程:main
可以看到,subscribe方法运行在子线程中(也就是订阅线程运行在名为RxCachedThreadScheduler-1的一个子线程中,上文提到该线程是由RxJava实现的一个工厂类创建的),而observer运行在名为main的线程中,这个main线程就是UI线程。
看完了输出结果,接下来就看看这个observeOn(AndroidSchedulers.mainThread())是如何将线程切换到UI线程的,点进去看下:
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.CUSTOM)
public final Observable observeOn(Scheduler scheduler) {
//当出现异常时,默认无延迟发送错误。bufferSize()是缓冲区大小,RxJava设置了一个默认大小,为128。
return observeOn(scheduler, false, bufferSize());
}
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.CUSTOM)
public final Observable observeOn(Scheduler scheduler, boolean delayError, int bufferSize) {
ObjectHelper.requireNonNull(scheduler, "scheduler is null");
ObjectHelper.verifyPositive(bufferSize, "bufferSize");
//包装类,保存上游observable
return RxJavaPlugins.onAssembly(new ObservableObserveOn(this, scheduler, delayError, bufferSize));
}
熟悉的套路,跟调用subscribe.on方法时类似,只是多了一个验证缓冲区大小不为空的代码,这些我们都略过,直接看ObservableObserveOn这个类:
public final class ObservableObserveOn extends AbstractObservableWithUpstream {
final Scheduler scheduler;
final boolean delayError;
final int bufferSize;
public ObservableObserveOn(ObservableSource source, Scheduler scheduler, boolean delayError, int bufferSize) {
super(source);
this.scheduler = scheduler;
this.delayError = delayError;
this.bufferSize = bufferSize;
}
@Override
protected void subscribeActual(Observer super T> observer) {
//如果传入的调度器是TrampolineScheduler,则不切换线程,在当前线程调度
//但是调度的任务并不是马上执行,而是等待当前任务执行完毕再执行
if (scheduler instanceof TrampolineScheduler) {
source.subscribe(observer);
} else {
//创建工作者worker
Scheduler.Worker w = scheduler.createWorker();
//上游的subscribe,该方法会触发上游的subscribeActual,
//ObserveOnObserver也是一个包装类,保存下游的observer
source.subscribe(new ObserveOnObserver(observer, w, delayError, bufferSize));
}
}
//......代码省略
}
熟悉的装饰器模式:
1、ObservableObserveOn继承了AbstractObservableWithUpstream,其继承的ObservableSource类型的source成员变量用于保存上游的observable。
2、AndroidSchedulers.mainThread()为本次传入的scheduler,负责将线程切换到UI线程。
3、下游调用subscribe方法是触发=>当前observable的subscribeActual方法=>触发上游observable的subscribe方法=>传入参数包装类ObserveOnObserver(包装了下游的观察者observer)。
这里简要介绍下步骤3:
这里的source是上游的observable对象,source.subscribe()方法实际调用的是上游observable对象的subscribeActual方法,并将下游observer对象的包装类ObserveOnObserver作为参数传递进去,在上游observable对象的subscribeActual方法内,调用ObserveOnObserver包装类中的onSubscribe,onNext等方法,进而调用下游observer的onSubscribe,onNext等方法。
接下来看下ObserveOnObserver这个下游observer包装类:
static final class ObserveOnObserver extends BasicIntQueueDisposable
implements Observer, Runnable {
private static final long serialVersionUID = 6576896619930983584L;
//下游observer
final Observer super T> act