文章主要记录自己学习源码的过程,不会对如如何使用做过多介绍。自己是初学者,只是为了学习记录。
基于:
implementation ‘io.reactivex.rxjava2:rxandroid:2.1.0’
implementation ‘io.reactivex.rxjava2:rxjava:2.2.3’
介绍:
a library for composing asynchronous and event-based programs using observable sequences for the Java VM
一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库。
Rxjava是一种面向数据流和变化传播的开源库。所谓的数据流是指:只能以事先规定好的顺序被读取一次的数据的一个序列。变化传播可以理解为观察者模式,当被观察者发生了变化就需要去通知观察者,这就是变化传播。
举一个简单的栗子。
上图履带上的一系列产品就可以看作是数据流,他只能以事先规定好的顺序被处理,当我们给他加上盖子后其实就是对他做了变化,这种变化会被传播到下一个环节,这样看是不是很容易就理解了什么是数据流,什么是变化传播?
首先分析无背压版的流程
从最简单的代码开始分析:
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(5);
emitter.onNext(4);
emitter.onComplete();
}
}).subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer integer) {
Log.d(TAG,"onNext:"+integer);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
Log.d(TAG,"onComplete:");
}
});
打印结果:
D/MainActivity: onNext:5
D/MainActivity: onNext:4
D/MainActivity: onComplete:
从这个简单的代码可以看出有哪些基本元素:
- Observable 被观察者,不支持背压。
- Observer 观察者,用于接收数据。作为Observable的subscribe方法的参数。
- Disposable 用于取消订阅和获取当前的订阅状态。和RxJava1的Subscription
作用相当。 - Emitter 用于发射数据,本质上是对Observer的封装。
- ObservableOnSubscribe 当订阅时触发此接口。
在分析执行流程前先热个身
public interface Observer<T> {
void onSubscribe(@NonNull Disposable d);
void onNext(@NonNull T t);
void onError(@NonNull Throwable e);
void onComplete();
}
观察者是一个接口,它提供了4个方法,当上游(被观察者)调用onNext,onComplete,发生错误,都会将结果回调到观察者对应的方法中。
public interface ObservableOnSubscribe<T> {
void subscribe(@NonNull ObservableEmitter<T> emitter) throws Exception;
}
ObservableOnSubscribe也是一个接口,它里面只有一个subscribe方法,该方法接受ObservableEmitter类型参数。
执行流程源码分析:
上面的栗子中,首先调用Observable.create()方法并给它传入了一个ObservableOnSubscribe类型匿名对象,看看Observable.create()方法干了什么。
public static <T> Observable<T> create(ObservableOnSubscribe<T> source) {
ObjectHelper.requireNonNull(source, "source is null");
return RxJavaPlugins.onAssembly(new ObservableCreate<T>(source));
}
首先创建了ObservableCreate对象并把ObservableOnSubscribe匿名对象作为它的参数传进去。
RxJavaPlugins.onAssembly()这个方法又干了什么?
public static <T> Observable<T> onAssembly(@NonNull Observable<T> source) {
Function<? super Observable, ? extends Observable> f = onObservableAssembly;
if (f != null) {
return apply(f, source);
}
return source;
}
onObservableAssembly默认为空,因此这个方法直接将创建的ObservableCreate对象返回了。
接着又调用了subscribe()并将观察者传进去,其实是调用ObservableCreate对象的subscribe()方法,点进去ObservableCreate对象的subscribe()方法看一下会发现subscribe()方法是ObservableCreate父类Observable的方法。
Observable#
public final void subscribe(Observer<? super T> observer) {
ObjectHelper.requireNonNull(observer, "observer is null");
try {
//这里返回的就是我们传进来的观察者对象observer
observer = RxJavaPlugins.onSubscribe(this, observer);
//...
subscribeActual(observer);
//...
}
}
protected abstract void subscribeActual(Observer<? super T> observer);
接着直接调用了subscribeActual(observer)方法,该方法在父类Observable是一个抽象方法,具体由子类实现,因此它最终会走到ObservableCreate的subscribeActual()方法
ObservableCreate#subscribeActual(Observer<? super T> observer)
@Override
protected void subscribeActual(Observer<? super T> observer) {
CreateEmitter<T> parent = new CreateEmitter<T>(observer);//1
observer.onSubscribe(parent);//2
try {
source.subscribe(parent);//3
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
parent.onError(ex);//4 出现异常就调用观察者的onError方法
}
}
在注释1会创建CreateEmitter对象对观察者进行包装,注释2直接调用观察者的onSubscribe方法,看到没?观察者对象的onSubscribe方法就是这里被调用的。接下来注释3调用source.subscribe(parent)方法,这个source就是我们Observable.create()方法传入的ObservableOnSubscribe对象,回顾一下。
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(5);
emitter.onNext(4);
emitter.onComplete();
}
})
这样就直接把我们的观察者的包装对象CreateEmitter传进来了,在里面调用它的onNext(),onComplete最终都会直接调用观察者的onNext,onComplete方法。
static final class CreateEmitter<T> extends AtomicReference<Disposable>
implements ObservableEmitter<T>, Disposable {
final Observer<? super T> observer;
CreateEmitter(Observer<? super T> observer) {
this.observer = observer;
}
@Override
public void onNext(T t) {
if (t == null) {
onError(new NullPointerException("onNext called with null. Null values are generally not allowed in 2.x operators and sources."));
return;
}
if (!isDisposed()) {
observer.onNext(t);
}
}
//....省略部分代码。
@Override
public void onComplete() {
if (!isDisposed()) {
try {
observer.onComplete();
} finally {
dispose();
}
}
}
梳理:
1、首先调用Observable的create方法,并且传入一个ObservableOnSubscribe对象作为source。create返回一个ObservableCreate对象,该对象持有source。
2、调用ObservableCreate对象的subscribe方法,并将观察者传入,subscribe方法又会调用subscribeActual(observer)方法。
3、然后直接调用source的subscribe方法并将观察者包装对象传进去。
4、在source#subscribe方法中调用的onNext,onComplete方法,本质上就是直接调用观察者的方法。
分析完无背压的简单执行过程,再来看看有背压的。
有背压版的执行流程
还是从最简单的代码开始。
Flowable.create(new FlowableOnSubscribe<String>() {
@Override
public void subscribe(FlowableEmitter<String> emitter) throws Exception {
emitter.onNext("1");
emitter.onNext("2");
emitter.onComplete();
}
}, BackpressureStrategy.DROP)
.subscribe(new Subscriber<String>() {
@Override
public void onSubscribe(Subscription s) {
//响应式拉取
s.request(Integer.MAX_VALUE);
}
@Override
public void onNext(String s) {
Log.d(TAG,"onNext:"+s);
}
@Override
public void onError(Throwable t) {
}
@Override
public void onComplete() {
Log.d(TAG,"onComplete:");
}
});
执行结果:
D/MainActivity: onNext:1
D/MainActivity: onNext:2
D/MainActivity: onComplete:
基本元素
- Flowable 被观察者,支持背压,和无背压版的Observable对应。
- Subscriber 观察者,作为Flowable的subscribe方法的参数。
- Subscription 支持背压,用于响应式拉取。
- FlowableOnSubscribe 当订阅时会触发此接口的调用。
- FlowableEmitter 发射器,用于发射数据。
跟着代码走
首先调用了Flowable的create方法,create方法接受两个参数,1、FlowableOnSubscribe匿名对象。2、背压策略 BackpressureStrategy.DROP
FlowableOnSubscribe是一个接口。
public interface FlowableOnSubscribe<T> {
void subscribe(@NonNull FlowableEmitter<T> emitter) throws Exception;
}
背压策略使用的是枚举类型。有下面几种策略
public enum BackpressureStrategy {
/**
* OnNext事件的写入没有任何缓冲或丢弃。下游必须处理任何溢出。
*/
MISSING,
/**
* 如果上游发的过快,下游的接收跟不上就通知MissingBackpressureException异常给下游
*/
ERROR,
/**
* 缓存所有的上游数据,直到下游可以处理。
*/
BUFFER,
/**
* 如果上游发的过快下游跟不上,就丢弃上游最近发送的数据
*/
DROP,
/**
* 如果上游发的过快,下游跟不上,只保留最新发送的数据,覆盖之前任意的数据。
*/
LATEST
}
为什么要有背压策略?通常当上下游处于不同的线程,上游发送的数据过快,但是下游处理的很慢,处理能力跟不上上游的发送速率。这时候就需要背压策略了,它是异步环境下产生的原因、发送和处理速度不统一、是一种流速控制解决策略。
继续看create方法,它做了什么呢?
Flowable#create()
public static <T> Flowable<T> create(FlowableOnSubscribe<T> source, BackpressureStrategy mode) {
return RxJavaPlugins.onAssembly(new FlowableCreate<T>(source, mode));
}
可以看到Flowable#create()方法创建并返回了FlowableCreate对象,该对象持有匿名对象(source)和背压策略(mode)。RxJavaPlugins#onAssembly()方法在前面已经分析过,默认情况下它直接将参数返回。
紧接着调用FlowableCreate对象的subscribe方法并将观察者(Subscriber)对象传递进去,继续跟进发现subscribe()方法其实是FlowableCreate父类Flowable的方法。
Flowable#subscribe()
public final void subscribe(Subscriber<? super T> s) {
if (s instanceof FlowableSubscriber) {
subscribe((FlowableSubscriber<? super T>)s);//1
} else {
ObjectHelper.requireNonNull(s, "s is null");
subscribe(new StrictSubscriber<T>(s));
}
}
接着会走注释1代码,继续跟进
Flowable#subscribe()
public final void subscribe(FlowableSubscriber<? super T> s) {
//...
try {
Subscriber<? super T> z = RxJavaPlugins.onSubscribe(this, s);//2
subscribeActual(z);
}
//...
}
注释2处的代码不用管,默认返回的就是我们传进来的观察者s(z==s),接着调用subscribeActual(z)方法,将我们观察者对象直接传进去,Flowable的subscribeActual()方法是一个抽象方法,所以这里会执行到FlowableCreate的subscribeActual()方法,有没有发现思想和无背压是一样的?
当我们调用FlowableCreate的subscribe方法然后会将创建的观察者对象(Subscriber)传入subscribeActual()方法。
接着看看FlowableCreate的subscribeActual()方法干了什么?
FlowableCreate#subscribeActual()
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);//1
break;
}
case LATEST: {
emitter = new LatestAsyncEmitter<T>(t);
break;
}
default: {
emitter = new BufferAsyncEmitter<T>(t, bufferSize());
break;
}
}
t.onSubscribe(emitter);//2 调用观察者的onSubscribe方法
try {
source.subscribe(emitter);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
emitter.onError(ex); //出现异常就调用onError方法
}
}
首先是根据我们采取的背压策略创建对应的发射器,栗子中采取的是BackpressureStrategy.DROP,因此会创建创建DropAsyncEmitter对象作为发射器,该对象持有下游的观察者对象。
static final class DropAsyncEmitter<T> extends NoOverflowBaseAsyncEmitter<T> {
DropAsyncEmitter(Subscriber<? super T> downstream) {
super(downstream);
}
//...
}
然后在注释2直接调用了下游观察者的onSubscribe()方法,接着调用source的subscribe方法,并将持有下游观察者的发射器传进去,这个source就是我们的FlowableOnSubscribe匿名对象。
Flowable.create(new FlowableOnSubscribe<String>() {
@Override
public void subscribe(FlowableEmitter<String> emitter) throws Exception {
//调用发射器的onNext、onComplete方法
emitter.onNext("1");
emitter.onNext("2");
emitter.onComplete();
}
}, BackpressureStrategy.DROP)
现在发射器传给subscribe方法了,因此,我们在它里面调用的一系列onNext方法和onComplete方法其实都是调用这个发射器的onNext方法、onComplete方法。我们可以猜想下,在这个发射器里面最终还是调用了下游观察者的onNext方法、onComplete方法,因为这个发射器是根据不同的背压策略创建的,所以它也负责了背压的工作,是不是呢,接着分析DropAsyncEmitter这个类。
static final class DropAsyncEmitter<T> extends NoOverflowBaseAsyncEmitter<T> {
private static final long serialVersionUID = 8360058422307496563L;
DropAsyncEmitter(Subscriber<? super T> downstream) {
super(downstream);
}
}
DropAsyncEmitter这个发射器代码就这点,在构造方法中直接将下游的观察者传给父类构造( super(downstream)),而且在DropAsyncEmitter这个类中也没有看到onNext、onComplete方法,继续跟踪父类看看。
DropAsyncEmitter#
abstract static class NoOverflowBaseAsyncEmitter<T> extends BaseEmitter<T> {
private static final long serialVersionUID = 4127754106204442833L;
NoOverflowBaseAsyncEmitter(Subscriber<? super T> downstream) {
super(downstream);
}
@Override
public final void onNext(T t) {
if (isCancelled()) { //如果被取消就直接返回
return;
}
if (t == null) {
onError(new NullPointerException("onNext called with null. Null values are generally not allowed in 2.x operators and sources."));
return;
}
if (get() != 0) { //1
downstream.onNext(t); //2
BackpressureHelper.produced(this, 1); //3
} else {
onOverflow(); //4
}
}
abstract void onOverflow();
}
重点看注释1、2、3的代码,再注释1处获取我们设置的值。这个值在哪里设置的呢?还记得响应式拉取的代码吗?
Flowable.create(new FlowableOnSubscribe<String>() {
@Override
public void subscribe(FlowableEmitter<String> emitter) throws Exception {
emitter.onNext("1");
emitter.onNext("2");
emitter.onComplete();
}
}, BackpressureStrategy.DROP)
.subscribe(new Subscriber<String>() {
@Override
public void onSubscribe(Subscription s) {
//响应式拉取
s.request(Integer.MAX_VALUE);//设值
}
//...
});
没错,就是在这里设置,如果我们没有调用s.request(Integer.MAX_VALUE);进行响应式拉取,它的值就为0,自然就不能进行onNext的操作了,在注释3处,每次发射了一次数据后都会将值进行减1操作,比如我们如果调用s.request(5);表示我们只拉取5个数据,将value设置为5,第一次get()肯定是5,然后发射第一条数据,再将value减1,下次再get时,value就为4了,当发射了5条数据之后,get()到的value肯定为0,此时后面的数据就无法onNext了,会走else中的代码onOverflow();onOverflow这个方法是一个抽象方法,由具体的发射器子类实现,在DropAsyncEmitter中他是一个空实现 。可以看到BackpressureStrategy.DROP这种背压策略的思想比较简单。至于get()获取value、s.request(5)设置value、BackpressureHelper.produced(this, 1)将value减1,他们所操作的value其实是AtomicLong类的,观察DropAsyncEmitter的继承结构可以发现DropAsyncEmitter间接继承了AtomicLong类。
AtomicLong介绍
AtomicLong是用于对Long类型进行操作的类,在32位操作系统中,64位的long变量会被JVM当作两个32位来进行操作,所以不具有原子性。而使用AtomicLong能让long的操作保持原子型,它提供了一些设值,更新值获取值的方法。