转载请注明出处:http://blog.csdn.net/hjf_huangjinfu/article/details/78421118
概述
本文内容基于 RxJava 2.1.6 版本,RxAndroid 2.0.1版本,主要是探索一下 RxJava 的内部结构以及其工作流程。
1、看一个简单的例子
Observable
.fromArray(1, 2, 3, 4)
.filter(new Predicate<Integer>() {
@Override
public boolean test(Integer integer) throws Exception {
Log.e("O_O", "filter, Thread : " + Thread.currentThread().getName());
return integer % 2 == 0;
}
})
.observeOn(Schedulers.newThread())
.map(new Function<Integer, Integer>() {
@Override
public Integer apply(Integer integer) throws Exception {
Log.e("O_O", "map, Thread : " + Thread.currentThread().getName());
return integer * 2;
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer integer) {
Log.e("O_O", "integer : " + integer + ", Thread : " + Thread.currentThread().getName());
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
看一下输出:
11-02 09:53:38.050 17242-17284/cn.hjf.rxjavatest E/O_O: filter, Thread : RxCachedThreadScheduler-1
11-02 09:53:38.050 17242-17284/cn.hjf.rxjavatest E/O_O: filter, Thread : RxCachedThreadScheduler-1
11-02 09:53:38.050 17242-17284/cn.hjf.rxjavatest E/O_O: filter, Thread : RxCachedThreadScheduler-1
11-02 09:53:38.050 17242-17284/cn.hjf.rxjavatest E/O_O: filter, Thread : RxCachedThreadScheduler-1
11-02 09:53:38.050 17242-17285/cn.hjf.rxjavatest E/O_O: map, Thread : RxNewThreadScheduler-1
11-02 09:53:38.050 17242-17285/cn.hjf.rxjavatest E/O_O: map, Thread : RxNewThreadScheduler-1
11-02 09:53:38.080 17242-17242/cn.hjf.rxjavatest E/O_O: integer : 4, Thread : main
11-02 09:53:38.080 17242-17242/cn.hjf.rxjavatest E/O_O: integer : 8, Thread : main
嗯,没毛病,这段代码的作用就是:
1、在IO线程中,生成 [1,2,3,4] 这几个数字,然后从中选出偶数。
2、在新线程中,对选出来的偶数 [2,4] 进行乘法操作。
3、最后,交给主线程进行打印。
2、RxJava基本结构
上面的代码片段中,涉及到很多对象,下面整理一张类图。
首先分为两大块,第一块就是事件源模块,第二块就是(观察者)监听器模块,这两个模块之间使用
观察者模式来建立联系,
事件源模块,由于RxJava提供了很多操作符来对事件源进行操作,所以使用了
装饰器模式来设计整个事件源模块,事件源分为两大类,一个是原始事件源,直接继承于Observable,一个是事件处理类,继承于AbstractObservableWithUpstream。
Observer以一种
迭代器的形式存在,事件源采用push的方式来输出整个事件流。
观察者模块采用
代理的模式,因为事件流从源头到观察者的中间过程里面,可能会被处理(调度、过滤、转换等等)。
3、对象调用流程
每一步的对象调用流程,以及关键操作步骤,都在下图中有说明,从操作1到操作12,形成了一个调用链条。链条分为2块,第一块是subscribe链条(1~6),第二块是notify链条(7~12),为什么要区分,因为这个跟线程调度有关系,后面再说。
4、线程切换操作
RxJava提供了 Scheduler 来提供线程切换机制,主要的调度操作委托给其内部类 Worker 的 schedule 方法,schedule 方法是抽象的,所以每个不同的 Scheduler 都可以有不同的调度实现。
public abstract Disposable schedule(@NonNull Runnable run, long delay, @NonNull TimeUnit unit);
schedule 方法可以把一个 Runnable 提交到其他线程去执行。
RxJava内部提供了一些具体的 Scheduler 实现,这里先不管每种实现的区别,反正就是把操作调度到其他线程执行,这里主要看一下是怎么调度的。上面提到的两个操作,subscribeOn 和 observeOn ,subscribeOn 主要是影响 subscribe链 和 notify 链,而 observeOn 只能影响 notify 链。
看一下 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;
}
}
主要是调用了 subscribeActual 方法,它是抽象方法,具体的事件源去实现自己的订阅策略
protected abstract void subscribeActual(Observer<? super T> observer);
ObservableSubscribeOn
看一下 ObservableSubscribeOn 的 subscribeActual 方法: 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)));
}
重点关注一下这一句代码
scheduler.scheduleDirect(new SubscribeTask(parent))
SubscribeTask是什么?是一个Runnable
final class SubscribeTask implements Runnable
再看一下 SubscribeTask 里面做了什么
@Override
public void run() {
source.subscribe(parent);
}
ObservableObserveOn
再看一下 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));
}
}
我们不关注 if 里面的内容,它不执行线程切换,只是把操作放到后面执行,关注这段代码:
source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize));
在之前运行的线程中执行 subscribe 调用,再看一下 ObserveOnObserver ,它是一个 Runnable
static final class ObserveOnObserver<T> extends BasicIntQueueDisposable<T> implements Observer<T>, Runnable
在 onNext 中,调用了 Scheduler.Worker 的 schedule 方法,成功的把 notify 操作 切换到其他线程了。
@Override
public void onNext(T t) {
if (done) {
return;
}
if (sourceMode != QueueDisposable.ASYNC) {
queue.offer(t);
}
schedule();
}
void schedule() {
if (getAndIncrement() == 0) {
worker.schedule(this);
}
}
所以它只能影响 notify 链,而不能影响 subscribe 链。
5、事件过滤转换操作
简述一下事件过滤转换操作过程,这里只用 filter 来举例子。RxJava 所谓的操作符,只不过是生成不同的事件源对象(ObservableSource 子类的实例),事件源分为几大类:
原始事件流
单一事件流 :一个单一的事件源
组合事件流 :由多个单一或者组合事件源组合而成的组合事件流(merge等等)
单一事件流 :一个单一的事件源
组合事件流 :由多个单一或者组合事件源组合而成的组合事件流(merge等等)
装饰器流
转换流 :对事件进行加工处理后的事件流(filter等等)
调度流 :对事件执行线程的调度(subscribeOn等等)
转换流 :对事件进行加工处理后的事件流(filter等等)
调度流 :对事件执行线程的调度(subscribeOn等等)
这里看一下 filter 操作生成的事件流, 对应的对象是 ObservableFilter ,看一下 subscribeActual 方法:
@Override
public void subscribeActual(Observer<? super T> s) {
source.subscribe(new FilterObserver<T>(s, predicate));
}
subscribe 操作委托给内部的事件源去操作,然后用一个 FilterObserver 来包装原始的 Observer,看一下 FilterObserver 主要代码:
@Override
public void onNext(T t) {
if (sourceMode == NONE) {
boolean b;
try {
b = filter.test(t);
} catch (Throwable e) {
fail(e);
return;
}
if (b) {
actual.onNext(t);
}
} else {
actual.onNext(null);
}
}
内部基于一个 Predicate 对象来执行真正的过滤操作,如果满足过滤条件,该事件就继续向下分发,如果不符合,就被过滤掉,典型的代理模式。