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(),進行統一取消訂閱操作.

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