前言
最近跟朋友聊天,聊到了最近面试的高频题目就聊到了RxJava 的线程切换原理。我们Android 开发大部分应该 RxJava
都用的很6,RXJava + Retrofit + OkHttp
大礼包都用的贼6。自从用了 RxJava 之后 ,Handler 和 SyncTask 基本消失在日常代码中啦。所以本篇就从源码的角度分析 RxJava 线程切换的原理。
注意:
本篇的源码基于 RxJava 3.0.7, RxAndroid 3.0.0。还得配置基于JAVA8,否则会报错,因为RxAndroid 中的 AndroidSchedulers 用了 Lambada 表达式。
一、先来看一个实例
这里默认大家都会 RxJava 切换线程啦。为了更加清晰的分析,我将线程切换的代码拆开来写啦。
1. 被订阅者 Observable 如下:
Observable<Integer> createOb = Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(@NonNull ObservableEmitter<Integer> emitter) throws Throwable {
Log.e("RX_JAVA", "subscribe threadName = " + Thread.currentThread().getName());
emitter.onNext(1);
emitter.onNext(2);
emitter.onComplete();
}
});
2. 切换到工作(子)线程
ObservableSubscribeOn 是 Observable 的子类
ObservableSubscribeOn<Integer> ioSchedulerOb = (ObservableSubscribeOn<Integer>) createOb
.subscribeOn(Schedulers.io());
subscribeOn 方法如下:
public final Observable<T> subscribeOn(@NonNull Scheduler scheduler) {
Objects.requireNonNull(scheduler, "scheduler is null");
return RxJavaPlugins.onAssembly(new ObservableSubscribeOn<>(this, scheduler));
}
ObservableSubscribeOn 构造函数的传参 scheduler 表示的就是 IoScheduler
,这里就不详细说明原因了,很简单 去 Schedulers.io()
跟进去即可发现:
3. 切换到主线程
ObservableObserveOn<Integer> mainOb = (ObservableObserveOn<Integer>) ioSchedulerOb
.observeOn(AndroidSchedulers.mainThread());
3.1. AndroidSchedulers.mainThread() 如下:
public static Scheduler mainThread() {
return RxAndroidPlugins.onMainThreadScheduler(MAIN_THREAD);
}
继续跟进去 可以发现 切换到主线程的 Scheduler 是 HandlerScheduler
,如下:
static final Scheduler DEFAULT
= new HandlerScheduler(new Handler(Looper.getMainLooper()), true);
- 可以看到 Handler 获取了主线程的 Looper,即处理的消息是在主线程中执行的;
- true,表示的是消息是异步消息。
3.2 observeOn 方法
最终调用的代码是:RxJavaPlugins.onAssembly(new ObservableObserveOn<>(this, scheduler, delayError, bufferSize));
看看 ObservableObserveOn
的构造函数:
public ObservableObserveOn(ObservableSource<T> source, Scheduler scheduler, boolean delayError, int bufferSize) {
super(source);
this.scheduler = scheduler;
this.delayError = delayError;
this.bufferSize = bufferSize;
}
这里面的 source 在我所在代码中指的就是 ObservableSubscribeOn
,因为 我这是 ioSchedulerOb (ObservableSubscribeOn调用的 observeOn 方法。
scheduler 就是之前说的 HandlerScheduler
。
其他2个参数不在本次分析之中。
4. 订阅者 Observer
Observer<Integer> observer = new Observer<Integer>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
Log.e("RX_JAVA", "onSubscribe threadName = " + Thread.currentThread().getName());
try {
Thread.sleep(1_000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void onNext(@NonNull Integer integer) {
Log.e("RX_JAVA", "integer = " + integer + ", threadNmae = " + Thread.currentThread().getName());
}
@Override
public void onError(@NonNull Throwable e) {
Log.e("RX_JAVA", "onError");
}
@Override
public void onComplete() {
Log.e("RX_JAVA", "onComplete");
}
};
5. 订阅
mainOb.subscribe(observer);
注意:
- 之所以将切成线程转换成各自的 Observable 是为了便于理解。
二、订阅的源码分析:
public final void subscribe(@NonNull Observer<? super T> observer) {
Objects.requireNonNull(observer, "observer is null");
try {
observer = RxJavaPlugins.onSubscribe(this, observer);
Objects.requireNonNull(observer, "The RxJavaPlugins.onSubscribe hook returned a null Observer. Please change the handler provided to RxJavaPlugins.setOnObservableSubscribe for invalid null returns. Further reading: https://github.com/ReactiveX/RxJava/wiki/Plugins");
subscribeActual(observer);
} catch (NullPointerException e) { // NOPMD
throw e;
} catch (Throwable e) {
。。。
}
}
observable的订阅方法关键一句subscribeActual(observer)
,这里提一句,所有的被观察者的订阅入口都是subscribeActual方法,而subscribeActual在被观察者中是抽象方法,因此看对应的observable子类实现的逻辑。
这里由于已经切换到主线程的 Observable 即 调用的是 ObservableObserveOn
的 subscribeActual 方法如下:
protected void subscribeActual(Observer<? super T> observer) {
// 上面分析了 scheduler 是 HandlerScheduler,所以条件不满足
if (scheduler instanceof TrampolineScheduler) {
source.subscribe(observer);
} else {
Scheduler.Worker w = scheduler.createWorker();
source.subscribe(new ObserveOnObserver<>(observer, w, delayError, bufferSize));
}
}
这里 主要分析 2个方法 scheduler.createWorker()
和 source.subscribe(new ObserveOnObserver<>(observer, w, delayError, bufferSize));
2.1 scheduler.createWorker() 方法
public Worker createWorker() {
return new HandlerWorker(handler, async);
}
HandlerWorker 是 HandlerScheduler 的内部类,这里暂且不表。
2.2 source.subscribe(observer)
上面分析了 source 指的是 ObservableSubscribeOn,所以调用 ObservableSubscribeOn 中的 subscribe 方法。
observer 是 ObservableObserveOn的内部类 ObserveOnObserver
。
ObservableSubscribeOn 中没有重写 subscribe 方法,所以调用的就是 Observable 的 subscribe 跟前面的一样,主要代码就是 subscribeActual(observer);
public final void subscribe(@NonNull Observer<? super T> observer) {
Objects.requireNonNull(observer, "observer is null");
try {
。。。
subscribeActual(observer);
} catch (NullPointerException e) { // NOPMD
throw e;
} catch (Throwable e) {
。。。
}
}
由于此时的 Observable 是 ObservableSubscribeOn ,所以走到 ObservableSubscribeOn 的 subscribeActual 方法:
@Override
public void subscribeActual(final Observer<? super T> observer) {
// SubscribeOnObserver 是 ObservableSubscribeOn 的内部类 ObserveOnObserver
final SubscribeOnObserver<T> parent = new SubscribeOnObserver<>(observer);
// observer 就是前面说的 ObservableObserveOn 内部类 ObserveOnObserver
observer.onSubscribe(parent);
parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)));
}
这里面 有2个方法需要注意:
1. observer.onSubscribe(parent);
即调用的是 ObservableSubscribeOn 的内部类 ObserveOnObserver 的 onSubscribe方法:
public void onSubscribe(Disposable d) {
if (DisposableHelper.validate(this.upstream, d)) {
this.upstream = d;
。。。
queue = new SpscLinkedArrayQueue<>(bufferSize);
downstream.onSubscribe(this);
}
}
downstream 就是我开始订阅的 Observer:
Observer<Integer> observer = new Observer<Integer>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
Log.e("RX_JAVA", "onSubscribe threadName = " + Thread.currentThread().getName());
try {
Thread.sleep(1_000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void onNext(@NonNull Integer integer) {
Log.e("RX_JAVA", "integer = " + integer + ", threadNmae = " + Thread.currentThread().getName());
}
@Override
public void onError(@NonNull Throwable e) {
Log.e("RX_JAVA", "onError");
}
@Override
public void onComplete() {
Log.e("RX_JAVA", "onComplete");
}
};
即 执行上面的 onSubscribe 方法 ,打印结果如下:
2. scheduler.scheduleDirect(new SubscribeTask(parent))
SubscribeTask 也是 ObservableSubscribeOn 的内部类,如下:
final class SubscribeTask implements Runnable {
private final SubscribeOnObserver<T> parent;
SubscribeTask(SubscribeOnObserver<T> parent) {
this.parent = parent;
}
@Override
public void run() {
source.subscribe(parent);
}
}
scheduler.scheduleDirect(Runnable run) 的作用其实就是将 run 提交到线程池中去执行,这样就相当于把线程切换到 工作线程 了。这里面就不展开了。
最终会执行 SubscribeTask 中的 run 方法,即 source.subscribe(parent)
,这里面的source 指的是 ObservableCreate, 因为 在前面的测试代码中 创建 切换到 io 线程的Observable 是 createOb .subscribeOn(Schedulers.io())
, 而 createOb 有是通过 Observable.create
创建的,看看 Observable.create 的代码如下:
public static <T> Observable<T> create(@NonNull ObservableOnSubscribe<T> source) {
Objects.requireNonNull(source, "source is null");
return RxJavaPlugins.onAssembly(new ObservableCreate<>(source));
}
即 source.subscribe
最终会调用的是 ObservableCreate 的 subscribeActual(observer)
方法,其中的 observer 就是 SubscribeOnObserver 的内部类 SubscribeOnObserver
protected void subscribeActual(Observer<? super T> observer) {
// observer 就是 SubscribeOnObserver 的内部类 SubscribeOnObserver
CreateEmitter<T> parent = new CreateEmitter<>(observer);
observer.onSubscribe(parent); // 1
try {
source.subscribe(parent); // 2
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
parent.onError(ex);
}
}
注1 : 执行的就是 SubscribeOnObserver
内部类SubscribeOnObserver的 onSubscribe 方法:
public void onSubscribe(Disposable d) {
// 设置 Disposable
DisposableHelper.setOnce(this.upstream, d);
}
注2 : source.subscribe(parent)
parent 就是 ObservableCreate 内部类 CreateEmitter;
这里面的 source就是我在测试代码中传进去的,如下:
Observable<Integer> createOb = Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(@NonNull ObservableEmitter<Integer> emitter) throws Throwable {
Log.e("RX_JAVA", "subscribe threadName = " + Thread.currentThread().getName());
emitter.onNext(1);
emitter.onNext(2);
emitter.onComplete();
}
});
执行的结果如下:
然后 里面执行发射器的发射, 即调用 ObservableCreate
中的 内部类 CreateEmitter 的 onNext 方法:
public void onNext(T t) {
if (t == null) {
onError(ExceptionHelper.createNullPointerException("onNext called with a null value."));
return;
}
if (!isDisposed()) {
observer.onNext(t);
}
}
observer.onNext(t) 调用的就是 ObservableSubscribeOn
内部类 SubscribeOnObserver
的 onNext 方法。
最终调用的是 ObservableObserveOn
的内部类 ObserveOnObserver
的onNext 方法:
public void onNext(T t) {
if (done) {
return;
}
if (sourceMode != QueueDisposable.ASYNC) {
queue.offer(t);
}
schedule();
}
schedule() 如下:
void schedule() {
if (getAndIncrement() == 0) {
worker.schedule(this);
}
}
worker.schedule(this) 最终调用的是 HandlerScheduler
中的 schedule,如下:
public Disposable schedule(Runnable run, long delay, TimeUnit unit) {
。。。
run = RxJavaPlugins.onSchedule(run);
ScheduledRunnable scheduled = new ScheduledRunnable(handler, run);
Message message = Message.obtain(handler, scheduled); // 注2
message.obj = this; // Used as token for batch disposal of this worker's runnables.
if (async) {
message.setAsynchronous(true);
}
handler.sendMessageDelayed(message, unit.toMillis(delay));
。。。
return scheduled;
}
注1 : Message message = Message.obtain(handler, scheduled)
这里是利用 Message的obtain来回收利用消息,代码如下:
public static Message obtain(Handler h, Runnable callback) {
Message m = obtain();
m.target = h;
m.callback = callback;
return m;
}
把 scheduled 方法设置为 Message 的 callback,我们知道给Message 设置了 callback后,那么通过 Handler发送消息后,执行的就是这个 callback 而不是 handler 的 handleMessage 方法。Handler 中 dispatchMessage 方法如下
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
注2 : 就是发送一个延时消息,没啥好说的。
那么消息发送后,消息的执行最终调用的就是 ObservableObserveOn
中内部类 ObserveOnObserver
的 run 方法:
public void run() {
if (outputFused) {
drainFused();
} else {
drainNormal();
}
}
最终调用的是 drainNormal():
void drainNormal() {
int missed = 1;
final SimpleQueue<T> q = queue;
final Observer<? super T> a = downstream;
for (;;) {
if (checkTerminated(done, q.isEmpty(), a)) {
return;
}
for (;;) {
。。。
a.onNext(v);
}
missed = addAndGet(-missed);
if (missed == 0) {
break;
}
}
}
最终调用的 a.next(),注意的是此时已经切到主线程了,是通过 Handler 实现的。这里的a 就是 测试代码中 订阅的 observer:
Observer<Integer> observer = new Observer<Integer>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
Log.e("RX_JAVA", "onSubscribe threadName = " + Thread.currentThread().getName());
try {
Thread.sleep(1_000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void onNext(@NonNull Integer integer) {
Log.e("RX_JAVA", "integer = " + integer + ", threadNmae = " + Thread.currentThread().getName());
}
@Override
public void onError(@NonNull Throwable e) {
Log.e("RX_JAVA", "onError");
}
@Override
public void onComplete() {
Log.e("RX_JAVA", "onComplete");
}
};
打印结果如下:
最后给出一个流程图,如下: