RxJava2 (二)取消订阅流程 dispose( ) 源码阅读

当前版本 2.2.19
RxJava2 (一)订阅流程源码阅读
RxJava2 (二)取消订阅流程 dispose( ) 源码阅读
RxJava2 (三)线程切换源码阅读
RxJava2 (四)切换UI主线程源码阅读
RxJava2 (五)just操作符源码阅读
RxJava2 (六)map操作符源码阅读

代码示例
Observable.create(new ObservableOnSubscribe<String>() {
    @Override
    public void subscribe(ObservableEmitter<String> emitter) throws Exception {
        emitter.onNext("Hello World");
        emitter.onComplete();
    }
})
        .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");
            }
        });
梳理对象
  • Observable:抽象类,Observable.create(ObservableOnSubscribe<T> source)最终创建一个ObservableCreate对象返回.
  • ObservableCreate:Observable的子类,实现了subscribeActual()方法.它内部持有ObservableOnSubscribe对象引用,
  • ObservableOnSubscribe:被观察者发射数据的是在ObservableOnSubscribe.subscribe()方法中调用CreateEmitter中的onNext(),onComplete()等方法.
  • 当执行Observable.subscribe()最终会调用ObservableCreate.subscribeActual(),所有的数据发射由这里开始.
  • CreateEmitter:它在ObservableCreate.subscribeActual()执行中被创建,它内部持有Observer引用.
  • 与取消订阅流程有关的点是,CreateEmitter实现了Disposable接口
    综上:CreateEmitter对象,可以发射数据,可以取消订阅流程,它向上抽取了两个接口,一个接口专门封装了发射数据的方法,一个接口专门处理取消订阅的方法.
Observer.onSubscribe(Disposable d)

当调用Observable.subscribe()最终会调用ObservableCreate.subscribeActual()

public final class ObservableCreate<T> extends Observable<T> {
    @Override
    protected void subscribeActual(Observer<? super T> observer) {
        CreateEmitter<T> parent = new CreateEmitter<T>(observer);
        // 观察者在这里调用了自身的onSubscribe()方法,传递过来的是CreateEmitter对象,不过onSubscribe(Disposable d)方法中的参数类型为Disposable.
        observer.onSubscribe(parent);
        ...
    }
}
// Disposable对象就是被当作参数传递到onSubscribe()方法中
.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");
    }
});
d.dispose(); 取消订阅

dispose()方法的具体实现需要去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()
            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出来的,所以其中并没有值,此时current是为null.
        Disposable current = field.get();
        // DISPOSED是一个枚举
        Disposable d = DISPOSED;
        if (current != d) {
            // 此时current为null,肯定与d不相等.
            // getAndSet(d)意思是将field对象中的旧值设置为d,并且返回旧值,那么current肯定还是为null.
            // 执行到这一步,AtomicReference<Disposable>对象中就存在一个枚举对象了.
            current = field.getAndSet(d);
            if (current != d) {
                if (current != null) {
                    current.dispose();
                }
                return true;
            }
        }
        return false;
    }
    // 判断传入的枚举类是否和当前枚举类相等.
    // 如果相等,代表订阅已经取消了
    // 如果不相等,代表订阅没有取消
    public static boolean isDisposed(Disposable d) {
        return d == 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对象中存入一个枚举对象.
            // CreateEmitter.get() 获取的就是这个枚举
            // 上面有分析过
            // 传入的枚举对象如果和枚举类中的枚举对象地址值相同,代表订阅已经取消了
            // 如果地址值不相同,代表订阅没有取消
            return DisposableHelper.isDisposed(get());
        }
    }
}
CompositeDisposable

简单说下CompositeDisposable,它可以批量管理RxJava批量取消订阅操作.

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; // 创建Set集合
                    if (set == null) {
                        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中有多个RxJava订阅,我想在Activity销毁的时候统一对这些订阅进行取消,那么就可以先将Disposable对象都add到CompositeDisposable对象中,等到Activity执行onDestroy生命周期的时候调用CompositeDisposable对象的dispose(),进行统一取消订阅操作.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章