本文将讲解两个知识点
1.RxJava的数据分发和接收流程,即Observable(可观察者)如何分发数据和Observer(观察者)如何订阅数据
2.RxJava是如何通过Disposable来取消订阅的,让Observer中断接收Observable分发的数据
一:RxJava2.x的数据分发和接收
通过一个简单的例子来看看RxJava的使用
//1.为了方便理解,下面的代码可以这样理解,其中Observable是一个抽象可观察者,通过
//create方法创建一个真正的可观察者,其中参数ObservableOnSubscribe可以理解为
//可观察者的数据发射源,Integer是发射数据的类型
//2.下面的subscribe方法将触发可观察者的行为,参数Observer是一个原始的
//观察者,它将订阅可观察者发射的数据
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(@NonNull ObservableEmitter<Integer> e) throws Exception {
mRxOperatorsText.append("Observable emit 1" + "\n");
Log.d(TAG, "Observable emit 1" + "\n");
e.onNext(1);
mRxOperatorsText.append("Observable emit 2" + "\n");
Log.d(TAG, "Observable emit 2" + "\n");
e.onNext(2);
mRxOperatorsText.append("Observable emit 3" + "\n");
Log.d(TAG, "Observable emit 3" + "\n");
e.onNext(3);
mRxOperatorsText.append("Observable emit 4" + "\n");
Log.d(TAG, "Observable emit 4" + "\n" );
e.onNext(4);
}
}).subscribe(new Observer<Integer>() {
private int i;
private Disposable mDisposable;
@Override
public void onSubscribe(@NonNull Disposable d) {
mRxOperatorsText.append("onSubscribe : " + d.isDisposed() + "\n");
Log.d(TAG, "onSubscribe : " + d.isDisposed() + "\n" );
mDisposable = d;
}
@Override
public void onNext(@NonNull Integer integer) {
mRxOperatorsText.append("onNext : value : " + integer + "\n");
Log.d(TAG, "onNext : value : " + integer + "\n" );
}
@Override
public void onError(@NonNull Throwable e) {
mRxOperatorsText.append("onError : value : " + e.getMessage() + "\n");
Log.d(TAG, "onError : value : " + e.getMessage() + "\n" );
}
@Override
public void onComplete() {
mRxOperatorsText.append("onComplete" + "\n");
Log.d(TAG, "onComplete" + "\n" );
}
});
输出结果如下:
RxJava框架的设计是基于一个观察者模式,例子中create方法创建的可观察者属于原始可观察者,它持有一个数据发射源,然后观察者通过订阅便可以接收到可观察者发射的数据,这些属于设计思想的范畴,下面来看看源码是如何实现的
1.创建可观察者
public static <T> Observable<T> create(ObservableOnSubscribe<T> source) {
ObjectHelper.requireNonNull(source, "source is null");
return RxJavaPlugins.onAssembly(new ObservableCreate<T>(source));
}
create方法返回一个ObservableCreate实例,它属于真正的可观察者,而Observable是抽象的可观察者,构造函数接收的source为数据发射源,由ObservableOnSubscribe接口实现
public interface ObservableOnSubscribe<T> {
void subscribe(@NonNull ObservableEmitter<T> e) throws Exception;
}
subscribe是我们要实现的接口方法,接收一个ObservableEmitter参数,这个参数可以理解为数据发射器,此接口有如下方法
public interface ObservableEmitter<T> extends Emitter<T> {
void setDisposable(@Nullable Disposable d);
void setCancellable(@Nullable Cancellable c);
boolean isDisposed();
@NonNull
ObservableEmitter<T> serialize();
}
public interface Emitter<T> {
void onNext(@NonNull T value);
void onError(@NonNull Throwable error);
void onComplete();
}
可以看到几个常用的方法,来看看可观察者ObservableCreate的构造函数
public ObservableCreate(ObservableOnSubscribe<T> source) {
this.source = source;
}
看到可观察者将持有数据发射源的引用,可以肯定的是,可观察者就是通过这个source来发射数据的
2.可观察者接受订阅行为,将触发数据的发射
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);
RxJavaPlugins.onError(e);
NullPointerException npe = new NullPointerException("Actually not, but can't throw other exceptions due to RS");
npe.initCause(e);
throw npe;
}
}
subscribe方法可以理解为可观察者接受订阅,参数是一个观察者,然后调用subscribeActual,这是在Observable中的一个抽象方法,我们去看ObservableCreate中是如何实现的
@Override
protected void subscribeActual(Observer<? super T> observer) {
//创建一个数据发射器,参数为观察者
CreateEmitter<T> parent = new CreateEmitter<T>(observer);
//首先调用观察者的onSubscribe方法,代表观察者实现订阅,
observer.onSubscribe(parent);
try {
//执行数据发射源的subscribe方法,传参数据发射器,这个发射源source就是例子中我们
//实现的ObservableOnSubscribe接口,此时代表可观察者开始发射数据了
source.subscribe(parent);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
parent.onError(ex);
}
}
可以看到,发射源进行数据的发射最终由发射器来执行,发射器持有原始观察者的引用,来看看发射器是如何实现的
static final class CreateEmitter<T>
extends AtomicReference<Disposable>
implements ObservableEmitter<T>, Disposable {
private static final long serialVersionUID = -3434801548987643227L;
//数据接收者
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()) {
//回调接收者的onNext方法
observer.onNext(t);
}
}
@Override
public void onError(Throwable t) {
if (t == null) {
t = new NullPointerException("onError called with null. Null values are generally not allowed in 2.x operators and sources.");
}
if (!isDisposed()) {
try {
observer.onError(t);
} finally {
dispose();
}
} else {
RxJavaPlugins.onError(t);
}
}
@Override
public void onComplete() {
if (!isDisposed()) {
try {
observer.onComplete();
} finally {
dispose();
}
}
}
@Override
public void setDisposable(Disposable d) {
DisposableHelper.set(this, d);
}
@Override
public void setCancellable(Cancellable c) {
setDisposable(new CancellableDisposable(c));
}
@Override
public ObservableEmitter<T> serialize() {
return new SerializedEmitter<T>(this);
}
@Override
public void dispose() {
DisposableHelper.dispose(this);
}
@Override
public boolean isDisposed() {
return DisposableHelper.isDisposed(get());
}
}
发射器中实现的方法有onNext、onError、onComplete等等,比如onNext方法中,首先判断发射的数据不能为null,否则抛出异常,然后通过isDisposed判断数据的接收是否被中断,如果没有则调用接收者的onNext方法接收数据
发射器还实现Disposable接口,此接口有两个方法:dispose和isDisposed方法,接收者可调用dispose方法中断数据的接收,接收者可以在onSubscribe中获得Disposed,这也是为什么发射数据之前要先调用接收者的onSubscribe方法,将Disposed传递给它
到这里我们明白RxJava中的一个最简单的数据分发和接收原理,为什么说是最简单呢,因为这里只包含了一个可观察者和观察者,即原始可观察者和原始观察者,而在实际应用中,整个过程可能会有多个可观察者和观察者串联在一起,这将复杂很多,在后面的文章会看到
二:RxJava 2.x中取消订阅的原理
RxJava中可以通过Disposable的dispose方法来取消数据的订阅,取消订阅以后Observer就不再接收到上游数据,但只是接收者不接收,发射者还是照样发射的,如下
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(@NonNull ObservableEmitter<Integer> e) throws Exception {
mRxOperatorsText.append("Observable emit 1" + "\n");
Log.d(TAG, "Observable emit 1" + "\n");
e.onNext(1);
mRxOperatorsText.append("Observable emit 2" + "\n");
Log.d(TAG, "Observable emit 2" + "\n");
e.onNext(2);
mRxOperatorsText.append("Observable emit 3" + "\n");
Log.d(TAG, "Observable emit 3" + "\n");
e.onNext(3);
//e.onComplete();
mRxOperatorsText.append("Observable emit 4" + "\n");
Log.d(TAG, "Observable emit 4" + "\n" );
e.onNext(4);
}
}).subscribeOn(Schedulers.io()) //切换到io线程
.observeOn(AndroidSchedulers.mainThread()) //切换到主线程
.subscribe(new Observer<Integer>() {
private int i;
private Disposable mDisposable;
@Override
public void onSubscribe(@NonNull Disposable d) {
mRxOperatorsText.append("onSubscribe : " + d.isDisposed() + "\n");
Log.d(TAG, "onSubscribe : " + d.isDisposed() + "\n" );
mDisposable = d;
}
@Override
public void onNext(@NonNull Integer integer) {
mRxOperatorsText.append("onNext : value : " + integer + "\n");
Log.d(TAG, "onNext : value : " + integer + "\n" );
i++;
if (i == 2) {
// 在RxJava 2.x 中,新增的Disposable可以做到切断的操作,让Observer观察者不再接收上游事件
mDisposable.dispose();
mRxOperatorsText.append("onNext : isDisposable : " + mDisposable.isDisposed() + "\n");
Log.d(TAG, "onNext : isDisposable : " + mDisposable.isDisposed() + "\n");
}
}
@Override
public void onError(@NonNull Throwable e) {
mRxOperatorsText.append("onError : value : " + e.getMessage() + "\n");
Log.d(TAG, "onError : value : " + e.getMessage() + "\n" );
}
@Override
public void onComplete() {
mRxOperatorsText.append("onComplete" + "\n");
Log.d(TAG, "onComplete" + "\n" );
}
});
在Observer的onNext方法中,当接收到第二个数据的时候,调用Disposable的dispose取消订阅,来看看输出结果
发射者一共发射了四个数字,接收者只接收到前面两个数字,那是因为在接收到第二个数字的时候,用Disposed中断了数据的接收
@Override
public void dispose() {
DisposableHelper.dispose(this);
}
@Override
public boolean isDisposed() {
return DisposableHelper.isDisposed(get());
}
调用了DisposableHelper的dispose方法,其中DisposableHelper是一个枚举类,来看看它的dispose方法
public static boolean dispose(AtomicReference<Disposable> field) {
Disposable current = field.get();
Disposable d = DISPOSED;
if (current != d) {
current = field.getAndSet(d);
if (current != d) {
if (current != null) {
current.dispose();
}
return true;
}
}
return false;
}
参数是CreateEmitter,因为CreateEmitter继承了AtomicReference,其实AtomicReference保存Disposable的引用,属于线程安全的原子操作。上面方法中,DISPOSED是枚举DisposableHelper的一个单例,其实就是将DISPOSED单例保存到AtomicReference<Disposable>中
在判断当前接收有没有被中断时候调用isDisposed,然后是DisposableHelper.isDisposed(get()),其实是判断当前AtomicReference中有没有保存DISPOSED单例,有代表已经中断接收数据了,否则没有,如下
public boolean isDisposed() {
return DisposableHelper.isDisposed(get());
}
public static boolean isDisposed(Disposable d) {
return d == DISPOSED;
}
在CreateEmitter发射器的onNext方法,首先调用isDisposed方法判断有没有中断订阅,如果没有才让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);
}
}
这就是RxJava中取消订阅事件的原理了