本文主要从原理上去理解RxJava,不涉及复杂的操作符讲解。
先看个简单例子:
Observable
.create(ObservableOnSubscribe<String> {
it.onNext("")
})//-------》 create返回的observable简称A
.subscribeOn(Schedulers.newThread())// ------》 同理这个简称B
.observeOn(Schedulers.newThread()) //-------》 简称C
.subscribe {
}
追踪Observable类,可以看出它是个抽象类,而且实现了ObservableSource接口,这接口非常重要(抽象类加接口,配合不错),先从ObservableSource最重要的方法subscribe开始理解:(只截取一部分)
@SchedulerSupport(SchedulerSupport.NONE)
@Override
public final void subscribe(Observer<? super T> observer) {
ObjectHelper.requireNonNull(observer, "observer is null");
try {
observer = RxJavaPlugins.onSubscribe(this, observer);
ObjectHelper.requireNonNull(observer, "Plugin returned null Observer");
subscribeActual(observer);
看,接口方法subscribe中调用了subscribeActual,这是Observable的抽象方法,先解释一下大部分的操作符都是继承了Observable,
所以每个操作符类的subscribeActual才是最核心的。
先看create做了啥:
public static <T> Observable<T> create(ObservableOnSubscribe<T> source) {
ObjectHelper.requireNonNull(source, "source is null");
return RxJavaPlugins.onAssembly(new ObservableCreate<T>(source));
}
就是返回了一个子类的实例,而且把ObservableOnSubscribe接口包装进去。
这个子类截全一点,好解释一些。先看最重要的subscribeActual,传了个Observer接口进来(先打个问号,这是什么?),创建了一个发射器,然后到最核心的是调用了source.subscribe(parent),牛逼了,此时,你可以把这个source理解为上游,上游执行了订阅方法。
public final class ObservableCreate<T> extends Observable<T> {
final ObservableOnSubscribe<T> source;
public ObservableCreate(ObservableOnSubscribe<T> source) {
this.source = source;
}
@Override
protected void subscribeActual(Observer<? super T> observer) {
CreateEmitter<T> parent = new CreateEmitter<T>(observer);
observer.onSubscribe(parent);
try {
source.subscribe(parent);
} catch (Throwable ex) {
接下来再看看subscribeOn操作符,你就会找到规律了:
public final class ObservableSubscribeOn<T> extends AbstractObservableWithUpstream<T, T> {
final Scheduler scheduler;
public ObservableSubscribeOn(ObservableSource<T> source, Scheduler scheduler) {
super(source);
this.scheduler = scheduler;
}
@Override
public void subscribeActual(final Observer<? super T> s) {
final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(s);
s.onSubscribe(parent);
//直接调用调度器,说白了就是开了个线程调用了runnable,而runnable使得上游执行订阅方法
parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)));
}
final class SubscribeTask implements Runnable {
private final SubscribeOnObserver<T> parent;
SubscribeTask(SubscribeOnObserver<T> parent) {
this.parent = parent;
}
@Override
public void run() {
source.subscribe(parent);
}
}
实际它也是继承了Observable,看到subscribeAtual没,Observer接口又被包装了,而且直接调用了调度器,SubscribeTask是个Runnable,它干了啥?
额,就是执行了上游的订阅方法。
回顾最上面的例子,将操作符做了简称,谁先执行了subscribe?是C,下面就写个调用链路:
C.subscribe(外层Observer) --> C.subscribeActual, Observer包装进C_Observer --> C的上游B.subscribe(C_Observer)
--> B.subscribeActual,C_Observer包装进了B_Observer --> B的上游A.subscribe(B_Observer) --> A.subscribeActual,B_Observer包装进了A_Observer --> A_Observer包装进了发射器emitter,ObservableOnSuscribe.subscribe(emitter)
看到没,我们可以在外层调用emitter的onNext等方法了。
至此,可以发现emitter发射数据时,observer是如何接收的,链路如下:
Emitter.onNext -> A_Observer.onNext()-> B_Observer.onNext() -> C_Observer.onNext()-> 外层observer.onNext()
通过看源码可以知道,每个操作符类中,都定义了一个静态的继承Observer接口的类,这就是包装了下游的Observer接口,并传递给上游。
至此,其实稍微可以总结一下RxJava的规律:
- 搞了个Observable抽象类,操作符的相关类都去继承它,这些类都要实现subscribeActual方法,这个方法里,上游都执行了订阅方法,看上面例子,C先执行订阅方法,再到B,再到A,所以订阅顺序就是由下往上的,而发射数据是由上往下。
- 每个操作符的构造函数都能包装上游,是因为接口ObservableSource。
- 像上面说的,每个操作符类中,都定义了一个静态的继承Observer接口的类,所以才可以包装下游的Observer接口,并通过上游的subscribe传递给上游。
- 当链式最下面的Observable实例调用subscribe的时候,才会触发最上面的ObservableOnSuscribe.subscribe回调。
- 最后强调一下,不要被相同的方法名所迷惑,初学者很容易被搞懵逼的,比如ObservableOnSuscribe和ObservableSource都有个subscribe方法,但它们的参数类型不一样,而且你要区分它们各自的用途。
- 比较常问的一个问题,多次subscribeOn,以哪个为准?看源码就知道了
parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)));
看到没,它是直接开了调度器的线程执行了上游的订阅方法(SubscribeTask源码在上面),举例有a、b、c 顺序的3个subscribeOn,订阅执行顺序是由下往上,c先执行,c的线程中执行了b.subscribe,b的线程中执行了a.subscribe,所以,无论你下面多少个subscribeOn,都只会以a的线程为准,所以答案是第一个的subscribeOn为准。