当前版本 2.2.19
RxJava2 (一)订阅流程源码阅读
RxJava2 (二)取消订阅流程 dispose( ) 源码阅读
RxJava2 (三)线程切换源码阅读
RxJava2 (四)切换UI主线程源码阅读
RxJava2 (五)just操作符源码阅读
RxJava2 (六)map操作符源码阅读
代码示例
// 创建被观察者
Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
emitter.onNext("Hello World");
emitter.onComplete();
}
});
// 订阅观察者
observable.subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
System.out.println("onSubscribe");
// 取消订阅后,ObservableEmitter发出的消息,观察者Observer将不会再收到.
d.dispose();
}
@Override
public void onNext(String s) {
System.out.println("onNext: " + s);
}
@Override
public void onError(Throwable e) {
System.out.println("onError");
}
@Override
public void onComplete() {
System.out.println("onComplete");
}
}
Observer.onSubscribe(Disposable)
- 调用
observable.subscribe(Observer)
方法后最终会调用ObservableCreate.subscribeActual()
方法, 在该方法中会调用观察者的onSubscribe(Disposable)
,详细的解释可以看上一篇文章
d.dispose();
取消订阅
对象d
是Disposable
类型, Disposable
是一个接口,具体实现需要看它的子类CreateEmitter
// ObservableCreate.CreateEmitter类
public final class ObservableCreate<T> extends Observable<T> {
static final class CreateEmitter<T> extends AtomicReference<Disposable> implements ObservableEmitter<T>, Disposable {
// 取消订阅
@Override
public void dispose() {
// this代表当前CreateEmitter对象,往下看.
DisposableHelper.dispose(this);
}
// 判断是否取消订阅
@Override
public boolean isDisposed() {
return DisposableHelper.isDisposed(get());
}
}
}
// DisposableHelper类
public enum DisposableHelper implements Disposable {
DISPOSED
;
// field为上一步传入的CreateEmitter对象,CreateEmitter继承了AtomicReference<Disposable>.
// AtomicReference<Disposable>知识可以看这两个博客:
// https://www.jianshu.com/p/84c75074fa03
// https://blog.csdn.net/zxc123e/article/details/52057289
public static boolean dispose(AtomicReference<Disposable> field) {
// 获取AtomicReference<Disposable>对象中的值,不过CreateEmitter对象是直接new出来的,
// 所以它的父类AtomicReference<Disposable>中并不存在Disposable这个值.此时current是为null.
Disposable current = field.get();
// DISPOSED是一个枚举,类型为DisposableHelper.
Disposable d = DISPOSED;
if (current != d) {
// 此时current为null,肯定与d不相等.
// getAndSet(d): 为field对象value设置为DisposableHelper.DISPOSED对象,并且返回旧值,旧值上面说过为null.
// 至此,field对象也就是上一步的CreateEmitter对象中value字段此时的值为DisposableHelper.DISPOSED对象.
current = field.getAndSet(d);
if (current != d) {
if (current != null) {
current.dispose();
}
return true;
}
}
return false;
}
// 判断CreateEmitter对象中value变量和当前枚举类相等.
// 如果相等,代表订阅已经取消了
// 如果不相等,代表订阅没有取消
public static boolean isDisposed(Disposable d) {
return d == DISPOSED;
}
}
通过分析,取消观察者与被观察者间的订阅关系,向CreateEmitter
对象中的value
字段赋值DisposableHelper.DISPOSED
对象就行了.
emitter.onNext("Hello World")
发射数据,最终会调用到CreateEmitter
中的onNext(T t)
方法,这个过程会判断订阅是否取消.下面来看下.
public final class ObservableCreate<T> extends Observable<T> {
static final class CreateEmitter<T> extends AtomicReference<Disposable> implements ObservableEmitter<T>, Disposable {
@Override
public void onNext(T t) {
...
if (!isDisposed()) {
observer.onNext(t);
}
}
// 判断是否取消订阅
@Override
public boolean isDisposed() {
// 如果CreateEmitter对象调用了dispose()方法,最终会向CreateEmitter对象中存入DisposableHelper.DISPOSED对象.
// CreateEmitter.get():就是获取当前CreateEmitter对象中value变量的值,也就是枚举对象.
// 上面有分析过
// 传入的枚举对象如果和枚举类中的枚举对象地址值相同,代表订阅已经取消了
// 如果地址值不相同,代表订阅没有取消
return DisposableHelper.isDisposed(get());
}
}
}
CompositeDisposable
简单说下CompositeDisposable
,它可以管理RxJava2
批量取消订阅操作.
CompositeDisposable mCompositeDisposable = new CompositeDisposable();
// 将所有的disposable对象都由mCompositeDisposable对象保管.
mCompositeDisposable.add(disposable);
下面看下CompositeDisposable
对象的add()
// CompositeDisposable类
public final class CompositeDisposable implements Disposable, DisposableContainer {
volatile boolean disposed; // 这个标记位是用来标记当前的CompositeDisposable对象是否已经执行了取消订阅的操作
@Override
public boolean add(@NonNull Disposable disposable) {
ObjectHelper.requireNonNull(disposable, "disposable is null");
if (!disposed) { // 假如当前CompositeDisposable对象还未执行取消操作
synchronized (this) {
if (!disposed) {// 假如当前CompositeDisposable对象还未执行取消操作
OpenHashSet<Disposable> set = resources;
if (set == null) {
// 创建Set集合
set = new OpenHashSet<Disposable>();
resources = set;
}
// 将disposable对象存入集合中
set.add(disposable);
return true;
}
}
}
// 假如当前的CompositeDisposable对象已经执行过了取消订阅的操作,那么就对传入的disposable进行取消操作
disposable.dispose();
return false;
}
// 对CompositeDisposable对象中set集合中的所有disposable进行取消订阅的操作
@Override
public void dispose() {
if (disposed) {
return;
}
OpenHashSet<Disposable> set;
synchronized (this) {
if (disposed) {
return;
}
disposed = true; // 将标记置为true,表示CompositeDisposable对象执行过了取消订阅的操作.
set = resources;
resources = null;
}
dispose(set);
}
void dispose(OpenHashSet<Disposable> set) {
if (set == null) {
return;
}
List<Throwable> errors = null;
Object[] array = set.keys();
for (Object o : array) {
if (o instanceof Disposable) {
try {
// 这里就是实际执行取消订阅的地方.
((Disposable) o).dispose();
}...
}
}
...
}
}
CompositeDisposable
对象主要用来批量取消订阅,比如Activity
中有多个RxJava2
订阅,我想在Activity
销毁的时候统一对这些订阅进行取消,那么就可以先将Disposable
对象都添加到CompositeDisposable
对象中,等到Activity
执行onDestroy
生命周期的时候调用CompositeDisposable.dispose()
,进行统一取消订阅操作.