本文记录我对 RxJava2 的理解与思考
RxJava 的操作流程可以总结为三部曲:
- 建厂
- 签约
- 开工
下面以简单的字符串打印阐述三部曲。
java 实现:
String[] ps = {"p1", "p2", "p3"};
for (String p : ps) {
System.out.println(p);
}
改为 rxjava 的实现:
Observable.just("p1", "p2", "p3")
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
System.out.println(s);
}
});
Observable.just("p1", "p2", "p3")
:建厂,这个厂生产"p1"、“p2”、“p3”。
.subscribe(new Consumer())
:签约、开工。
签约:跟 Consumer 确定合作关系。
开工:把"p1"、“p2”、"p3"发给 Consumer。
subscribe 内部执行过程:
subscribe(consumer)//签约
-->subscribe(observer)//签约
-->subscribeActual(observer)//开工
-->observer.onNext("p1")
-->consumer.accept("p1")
其实就是 Observable 持有 Observer 的引用,再在合适的时机调用 Observer 的方法。
上面使用 just 的 RxJava 写法比 Java 写法多了一点,但其实已经是一种封装,最原始的 RxJava 写法要更多:
Observable<String> observable = new Observable<String>() {
@Override
protected void subscribeActual(Observer<? super String> observer) {
String[] ps = {"p1", "p2", "p3"};
for (String p : ps) {
observer.onNext(p);
}
observer.onComplete();
}
};
Observer<String> observer = new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String s) {
System.out.println(s);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
};
observable.subscribe(observer);
原始代码同样符合三部曲:
下面以线程切换阐述三部曲。
java 实现:
new Thread(new Runnable() {
@Override
public void run() {
String[] ps = {"p1", "p2", "p3"};
for (String p : ps) {
System.out.println(p);
}
}
}).start();
rxjava 实现:
Observable<String> observable = new Observable<String>() {
@Override
protected void subscribeActual(Observer<? super String> observer) {
String[] ps = {"p1", "p2", "p3"};
for (String p : ps) {
observer.onNext(p);
}
observer.onComplete();
}
};
Observer<String> observer = new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String s) {
System.out.println(s);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
};
observable
.subscribeOn(Schedulers.io())
.subscribe(observer);
如何实现的,关键在这里。
observable
.subscribeOn(Schedulers.io())
.subscribe(consumer);
返回一个 ObservableSubscribeOn,它是一个 Observable(一个加工地)。
它继承了 AbstractObservableWithUpstream
,即有上游的 Observable(加工地的基类)。
它有一个 Scheduler
对象(关于 Scheduler,可见RxJava2:Scheduler 详解)。
一个 Observable 最关键的方法就是它的 subscribeActual,我们看下 ObservableSubscribeOn 的 subscribeActual 方法:
@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 SubscribeTask(parent)));
}
一步步分析:
parent = new SubscribeOnObserver(s)
里面生成了一个 SubscribeOnObserver
,它是一个 Observer(加工地厂长),内部还有一个 Observe(客户),相当于它自己也是个客户(相对上游而言)。
同时它也是一个 Disposable(可以提供给对方合同)。
同时它还有一个 Disposable 对象(可以接受对方的合同)。
s.onSubscribe(parent)
客户 s 接受了加工地厂长 parent 的合同,客户 s 可以持有这份合同(disposable),并单方面撕毁合同(disposable.dispose(),相当于 removeCallback、unregisterListener)。
parent.setDisposable()
加工地厂长来制定自己提供的合同内容。合同的内容是 scheduler.scheduleDirect(new SubscribeTask(parent))
。
scheduler.scheduleDirect(new SubscribeTask(parent))
这里是逻辑的重点。 在这里,scheduler 会按自己的策略执行 SubscribeTask,SubscribeTask 是一个 runnable,run 里面就是 source.subscribe(parent)
,source 是加工地的上游,parent 就是厂长自己,所以厂长在这里与上游签约。
即 subscribeOn 的厂长在跟给下游签约时,提供了一份合同,合同的内容是:厂长会与上游在 scheduler 提供的线程中签约。
如果原厂地没有特殊处理,它会在跟客户(或是加工地厂长)在签约的线程开工。所以,当使用了多个 subscribeOn() 的时候,只有第一个 subscribeOn() 起作用。因为只有离生产地最近的那个加工地厂长能决定它的上游——生产地的开工线程。
这也解释了为什么 subscribeOn 需要给下游提供一份合同,因为它会影响上游的生产过程,下游可以用合同去停止整个活动。
再看下 observeOn,会生成一个 ObservableObserveOn,它的 subscribeActual:
@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));
}
}
source 是上游,observeOn 自己直接跟上游签约,没有执行特殊操作,也没有提供给下游合同。
因为没有执行特殊操作,所有不会影响上游的生产过程,所有也不用取消,所有也不用给下游合同。它会在收到上游的合同时把它转交给下游(自己的 onSubscribe() 被调用时调用下游的 onSubscribe())。
它的作用主要在 ObserveOnObserver:
@Override
public void onNext(T t) {
if (done) {
return;
}
if (sourceMode != QueueDisposable.ASYNC) {
queue.offer(t);
}
schedule();
}
ObserveOnObserver 收到上游发送的产品,执行 schedule(),把产品提供给下游。
observeOn() 能够多次调用,就是因为 它的作用在于加工,加工的内容就是:在 Scheduler 提供的线程中把产品提供给下游。至于 subscribeOn 的加工内容,当然是没有加工,直接提供给下游。
再回顾一下: