Rxjava 过程分析一
说明
- 该文章是基于 Rxjava2 源码。
- 该篇只是讲述 Rxjava 建议的用法,不涉及操作符和线程切换, 后两个会有新的篇幅去写。 一步一步的来。
- 在源码中那些判空还有 Rxjava 中 RxJavaPlugins 钩子等在分析中去除(只关注用法和思想, 和主流程不管的暂时剔除)。
- 由于习惯, 和 Rxjava2 中的命名。 我称 emitter 为上游, 也就是发射水(数据)的源头, 结果回调给外部的 FlowableSubscriber, 我称它为下游。 上游流水流到下游!
最简单的使用
Flowable.create(new FlowableOnSubscribe<String>() {
@Override
public void subscribe(FlowableEmitter<String> emitter) throws Exception {
// emitter.onNext("");
// emitter.onError();
// emitter.onComplete();
}
}, BackpressureStrategy.LATEST).subscribe(new FlowableSubscriber<String>() {
@Override
public void onSubscribe(Subscription s) {
}
@Override
public void onNext(String s) {
}
@Override
public void onError(Throwable t) {
}
@Override
public void onComplete() {
}
});
引发的思考
- 调用 emitter 的 onNext、 onError、 onComplete, 就会回调 FlowableSubscriber 中对应的方法。 那么这两个对象是一个吗? 有什么联系呢?
- 我们把上述代码写好后, 会自动调用并回调, 那么上游发射器 emitter 是什么时候触发的呢? 该方法是什么时机和谁调用的呢?
源码分析
从创建开始
public static <T> Flowable<T> create(FlowableOnSubscribe<T> source, BackpressureStrategy mode) {
return new FlowableCreate<T>(source, mode);
}
简单吗大兄弟, 仅仅是创建了一个 FlowableCreate 类而已。 并对成员变量赋值。
简单说说下游
在开发中, 可能很多都有在用回调吧。 再次机会我也想说说回调是咋回事。 其实 java 中的常用的内部类回调, 还是 c 的函数指针, 或者其语言的闭包(swift), 其实不要把它们想的多么神奇。 就这么想, 我把一个实例地址或者函数地址给你了, 你在内部去调用我的方法, 自然就运行到了外面了。
订阅
public final void subscribe(FlowableSubscriber<? super T> s) {
try {
Subscriber<? super T> z = s;
subscribeActual(z);
} catch (NullPointerException e) {
throw e;
} catch (Throwable e) {
}
}
信息量很少, 只是调用了当前 Flowable 的 subscribeActual() 方法。 我们前面知道当前的 Flowable 是 FlowableCreate 对象, 所以进 FlowableCreate 中去看看做了什么事情。
public void subscribeActual(Subscriber<? super T> t) {
BaseEmitter<T> emitter;
switch (backpressure) {
case MISSING: {
emitter = new MissingEmitter<T>(t);
break;
}
case ERROR: {
emitter = new ErrorAsyncEmitter<T>(t);
break;
}
case DROP: {
emitter = new DropAsyncEmitter<T>(t);
break;
}
case LATEST: {
emitter = new LatestAsyncEmitter<T>(t);
break;
}
default: {
emitter = new BufferAsyncEmitter<T>(t, bufferSize());
break;
}
}
t.onSubscribe(emitter);
try {
source.subscribe(emitter);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
emitter.onError(ex);
}
}
我们这里不去讨论背压等问题, 所以我们只是关注主要流程和关键方法。 其中一眼就可以看到关键的一个就是在 try 块中的 source.subscribe(emitter); source 是什么呀? 就是我们在 new FlowableCreate 传进来的 Flowable.create(new FlowableOnSubscribe<String>()) 中 FlowableOnSubscribe 对象。 source 的 subscribe 这不就是运行了 外部 FlowableOnSubscribe 的 subscribe嘛, 所以外部调用 onNext, onError, onComplete 方法, 其实调用了 内部 emitter 中对应的方法。 我们以背压为 LATEST 为例看看 LatestAsyncEmitter 被调用的方法做了什么事情。 先多说一句, 初始化 emitter 时我们传入的是下游哦, 下游相应的方法调用了, 那么外部的就会看似回调出去拿到结果了!
我们以 onNext 为例, 看看 LatestAsyncEmitter 被调用到 onNext 做了什么事情。
public void onNext(T t) {
queue.set(t);
drain();
}
看到是先把结果存到了队列中, 我们不考虑背压, 所以我们看主要的大致流程哈。 显然下一个有用的代码就是 drain() 了。
void drain() {
final Subscriber<? super T> a = downstream;
final AtomicReference<T> q = queue;
// ......
T o = q.getAndSet(null);
// ......
a.onNext(o);
// ......
}
其中 downstream 就是我们外部的 FlowableSubscriber 及下游了。 我们可以看到, 简单的从队列中取出数据, 直接调用了下游的 onNext。 就这样数据就被从上游流向了下游。
前面的疑惑问题
- 上游和下游是一个东西吗? 它们的关系是什么?
这个问题从上面的分析已经很明显了。 上游和下游不是一个东西, 上游 emitter 调用相应的方法去回调下游的方法。
- 在哪一个时刻触发的事件流动呢?
其实是在上游 emitter 调用相应的方法那一刻, 比如调用 onNext。 那么是在哪一个时机触发调用的呢? 很明显是在订阅时, 调用了 subscribeActual 中又调用了上游的 subscribe(emitter) 触发了数据的流动。