核心问题:
- 为甚是被观察者订阅观察者
- RxJava执行的流程
为甚是被观察者订阅观察者
Observable.subscribe(Observer); 从字面上的理解是被观察者订阅观察者,比如报纸订阅了读者。但从开发者的角度来理解,就很正常 了。
RxJava这样设置的目的是为了流式Api的设计,还有就是Android中的观察者模式都是这样的写法,比如View.setOnClickListener(OnClickListener) : View就是被观察者,OnClickListener是观察者,他们通过setOnClickListener形成订阅关系。 一旦被观察者发生了什么事情(事件),就需要告知观察者,然后观察者会做出相应的措施。
RxJava执行的流程
从一个简单的示例代码说起:
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> e) throws Exception {
e.onNext(1);
e.onNext(2);
e.onComplete();
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Integer>() {
private Disposable mD = null;
@Override
public void onSubscribe(Disposable d) {
mD = d;
}
@Override
public void onNext(Integer value) {
if (1 == value) {
mD.dispose();
}
}
@Override
public void onError(Throwable e) {
KLog.d("e:" + e.toString());
}
@Override
public void onComplete() {
KLog.d("onComplete");
}
});
按照自上而下的顺序,开始吧
Observable.create(ObservableOnSubscribe source)
public static <T> Observable<T> create(ObservableOnSubscribe<T> source) {
ObjectHelper.requireNonNull(source, "source is null");
return RxJavaPlugins.onAssembly(new ObservableCreate<T>(source));
}
流程的第一步,创建了两个对象:ObservableOnSubscribe 和 ObservableCreate 。
ObservableCreate
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) {
Exceptions.throwIfFatal(ex);
parent.onError(ex);
}
}
//省略其他代码
}
ObservableCreate 继承Observable,在构造函数中保存了上一级创建的 ObservableOnSubscribe 对象的引用。
public abstract class Observable<T> implements ObservableSource<T>{...}
public interface ObservableSource<T> {
void subscribe(Observer<? super T> observer);
}
上面的2段源码清楚的看到,Observable 是一个抽象类,是 ObservableSource 的实现类,而 ObservableSource 类是一个接口,它表示事件源。内部只有一个方法 subscribe 该方法表示通过 Observer 订阅当前的事件源。那么事件发布的事件,在 Observer 订阅者中就会被收到。了解了 Observable 的顶层接口之后,我们就知道该体系最重要的一个功能那就是 subscribe 方法了,因此我们就重点关注子类的 subscribe 方法。
现在,把视角转到Observable的subscribe()方法来,看看它做了什么处理。
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);
} catch (NullPointerException e) { // NOPMD
throw e;
} catch (Throwable e) {
Exceptions.throwIfFatal(e);
// can't call onError because no way to know if a Disposable has been set or not
// can't call onSubscribe because the call might have set a Subscription already
RxJavaPlugins.onError(e);
NullPointerException npe = new NullPointerException("Actually not, but can't throw other exceptions due to RS");
npe.initCause(e);
throw npe;
}
}
protected abstract void subscribeActual(Observer<? super T> observer);
他把observer订阅者传递给subscribeActual(Observer observer)抽象方法,这意味着所有Observable的子类,我们只要关心 subscribeActual(observer); 这个方法就好的。
好的,那么我们就回到最开始的ObservableCreate,去看看他在subscribeActual()做了什么
@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) {
Exceptions.throwIfFatal(ex);
parent.onError(ex);
}
}
在上面的代码里面,先是创建了一个发射器CreateEmitter,然后回调给 observer#onSubscribe() ,最后是通知上一级的Observable(也就是代码里的source)你可以发送事件了。这边不太了解RxJava可能有疑问我为什么这么下定论?因为事件是在被观察者“订阅”观察者时后才发送的!!!
subscribeOn(Schedulers.io())
这个方法的作用是让上游事件切换线程的,不管它在整个流中使用了几次,只有第一次是有效的。why? 先把这个疑问放下,后面看看流程图就应该明白了。
public final Observable<T> subscribeOn(Scheduler scheduler) {
ObjectHelper.requireNonNull(scheduler, "scheduler is null");
return RxJavaPlugins.onAssembly(new ObservableSubscribeOn<T>(this, scheduler));
}
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);
parent.setDisposable(scheduler.scheduleDirect(new Runnable() {
@Override
public void run() {
source.subscribe(parent);
}
}));
}
//省略部分代码
}
是不是很熟悉,因为AbstractObservableWithUpstream也是继承自Observable。subscribeActual()方法里执行的也是相似的逻辑,只不过是多了scheduler线程相关的逻辑,这里先不进行详细分析。
abstract class AbstractObservableWithUpstream<T, U> extends Observable<U> implements HasUpstreamObservableSource<T> {
/** The source consumable Observable. */
protected final ObservableSource<T> source;
/**
* Constructs the ObservableSource with the given consumable.
* @param source the consumable Observable
*/
AbstractObservableWithUpstream(ObservableSource<T> source) {
this.source = source;
}
@Override
public final ObservableSource<T> source() {
return source;
}
}
这个抽象类也是保存了上一个Observable的引用。
observeOn(AndroidSchedulers.mainThread())
我猜这边应该是相似的代码。
public final class ObservableObserveOn<T> extends AbstractObservableWithUpstream<T, T> {
final Scheduler scheduler;
final boolean delayError;
final int bufferSize;
public ObservableObserveOn(ObservableSource<T> 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) {
if (scheduler instanceof TrampolineScheduler) {
source.subscribe(observer);
} else {
Scheduler.Worker w = scheduler.createWorker();
source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize));
}
}
//省略相关代码
}
果不其然,就不赘述了。
subscribe(Observer observer)
subscribe后,被观察者(Observable)一旦有发射什么事件,观察者(Observer)都可以接收事件。
总结
过程:断点调试,绘制流程图
还记得在介绍 #subscribeOn(Schedule)方法提出的那个问题?
无论我们在整个上游的事件流中使用了多少次#subscribeOn(Schedule)变换线程,只有第一次设置的有效。看了上面的流程图,相信应该明白了吧。
下一篇,讲述RxJava线程切换原理