“碼上理解”--- 手撕RxJava訂閱關係,事件發送和接收

RxJava簡單介紹

RxJava現在幾乎每個Android項目中都有它的身影,RxJava是使用了Rx(ReactiveX)函數庫的語言庫,Rx是一個函數庫,讓開發者可以利用可觀察序列和LINQ風格查詢操作符來編寫異步和基於事件的程序,除了RxJava,Rx幾乎支持了全部的流行編程語言,例如:RxJS、Rx.NET等等。

文章目的

通過一個栗子(創建操作符由很多,這裏以create操作符爲例),再結合源碼來理清RxJava 訂閱關係是如何實現的,以及舉例onNext事件發送和接收,粒度上本文關注流程實現相關代碼,無關於流程的代碼不關注。

環境搭建和代碼示例

配置和代碼很簡單,如下

    implementation 'io.reactivex.rxjava2:rxjava:2.1.0'
    implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
public class MainActivity extends AppCompatActivity {
    private Disposable disposable;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        rxJava1();
    }

    public void rxJava1(){
    	//創建操作符采用create
        Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> e) throws Exception {
                e.onNext("事件1");
            }
        }).subscribe(new Observer<String>() {
            @Override
            public void onSubscribe(Disposable d) {
                Log.i("RxJava","訂閱完成了");
                disposable = d;
            }

            @Override
            public void onNext(String s) {
                Log.i("RxJava",s);
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        });
    }
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (disposable != null)
            if (!disposable.isDisposed())
                disposable.dispose();
    }
}

運行結果

24075-24075/com.himi.rxjavaanalysis I/RxJava: 訂閱完成了
24075-24075/com.himi.rxjavaanalysis I/RxJava: 事件1

既然研究訂閱關係,那麼我從subscribe方法入手

subscribe()方法

由上面的例子所示,subscribe方法傳入了Observer對象(相當於觀察者),來點擊subscribe方法卡看源碼是怎麼實現的

public abstract class Observable<T> implements ObservableSource<T> {
    ...
	@SchedulerSupport(SchedulerSupport.NONE)
	    @Override
	    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");
				//重點是這句代碼,其它代碼是一些健壯性判斷或者添加hook等
	            subscribeActual(observer);
	        } catch (NullPointerException e) { // NOPMD
	            throw e;
	        } catch (Throwable e) {
	            Exceptions.throwIfFatal(e);
	            // can't call onError because no way to know if a Disposable has been set or not
	            // can't call onSubscribe because the call might have set a Subscription already
	            RxJavaPlugins.onError(e);
	
	            NullPointerException npe = new NullPointerException("Actually not, but can't throw other exceptions due to RS");
	            npe.initCause(e);
	            throw npe;
	        }
	    }
	    ...
}

我們看到subscribe方法是抽象類Observable中的方法,方法中以observer爲參數調用了subscribeActual(observer)方法,繼續查看subscribeActual方法的源碼

public abstract class Observable<T> implements ObservableSource<T>{
	...
    protected abstract void subscribeActual(Observer<? super T> observer);
    ...
}

發現subscribeActual方法是抽象類Observable的抽象方法,那哪裏實現了這個方法呢?
我們知道subscribe方法是Observable.create(new ObservableOnSubscribe< String>() {…})調用的,推測Observable.create(new ObservableOnSubscribe< String>() {})實現了Observable抽象方法,並實現了subscribeActual方法。那來看一下Observable.create(new ObservableOnSubscribe< String>() {…})具體做了什麼

Observable.create(new ObservableOnSubscribe< String>() {})

查看create()源碼

public abstract class Observable<T> implements ObservableSource<T>{
	...
    @CheckReturnValue
    @SchedulerSupport(SchedulerSupport.NONE)
    public static <T> Observable<T> create(ObservableOnSubscribe<T> source) {
        ObjectHelper.requireNonNull(source, "source is null");
        // hook
        return RxJavaPlugins.onAssembly(new ObservableCreate<T>(source));
    }
    ...
}

發現返回了一個Observable對象 RxJavaPlugins.onAssembly(new ObservableCreate(source)),參數是傳入的ObservableOnSubscribe對象,究竟這個方法將ObservableOnSubscribe怎麼樣了呢,繼續看RxJavaPlugins.onAssembly()的實現方式

    /**
     * Calls the associated hook function.
     * @param <T> the value type
     * @param source the hook's input value
     * @return the value returned by the hook
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    @NonNull
    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;
    }

由註釋可以瞭解,這個方法跟hook有關係,繼續看方法內部
Function<? super Observable, ? extends Observable> f = onObservableAssembly;
方法中判斷了如果f爲null 就返回參數,如果f不爲null,就返回apply方法的返回值,那onObservableAssembly在哪賦值的呢?
在這裏插入圖片描述
發現RxJavaPlugins的840行給其賦值了,我們順勢看一下
在這裏插入圖片描述
由註釋可以瞭解,這是設置hook的方法,發現是這個方法給onObservableAssembly賦值了,我們點擊setOnObservableAssembly方法查看哪裏由調用onObservableAssembly,發現程序中除了初始化的地方調用了setOnObservableAssembly(null),給onObservableAssembly賦值了null,其餘地方沒用到,所以,可以知道onAssembly的返回值就是傳入的ObservableCreate對象,也就是Observable.create()方法最終返回的是ObservableCreate對象。
此時我們可以推測一下,ObservableCreate肯定是Observable的實現類,也實現了subscribeActual方法,看一下源碼是否如此:

public final class ObservableCreate<T> extends Observable<T> {
    final ObservableOnSubscribe<T> source;

    public ObservableCreate(ObservableOnSubscribe<T> source) {
        this.source = source;
    }
	// 實現了subscribeActual
    @Override
    protected void subscribeActual(Observer<? super T> observer) {
    	//將觀察者observer包裝一下,放入發射器中
        CreateEmitter<T> parent = new CreateEmitter<T>(observer);
        //調用observer的onSubscribe方法,表示訂閱完成,
        //參數是CreateEmitter對象,CreateEmitter實現了Disposable接口,onSubscribe中可以拿到Disposable對象調用dispose
        observer.onSubscribe(parent);

        try {
        	//拿到ObservableOnSubscribe對象,回調subscribe方法,並將發射器帶過去,方便對事件發送
            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()) {
                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 dispose() {
            DisposableHelper.dispose(this);
        }

        @Override
        public boolean isDisposed() {
            return DisposableHelper.isDisposed(get());
        }
    }
}

不出意外,確實如推測的那樣,ObservableCreate類實現了subscribeActual抽象方法,也就是當執行subscribe訂閱方法的時候,是調用了ObservableCreate類的subscribeActual方法。其方法內幹了3件事情:
1.以observer爲參數創建了一個發射器
2.調用了observer的onSubscribe方法
3.調用了source的subscribe方法,並將發射器傳遞過去
我們先看第一件事

1.以observer爲參數創建了一個發射器

根據源碼我們可以知道,發射器中包含observer對象,也有與observer相對應的onNext、onError、onComplete回調方法,在發射器的回調方法中,執行了對應observer的回調方法,比方e.onNext中執行了observer.onNext
在這裏插入圖片描述

2.調用observer的onSubscribe方法

當RxJava配合retorfit+okhttp來請求網絡,如果請求網絡時需要加進度圈,我們通常在項目要在observer的onSubscribe方法中添加,原因是
1.onSubscribe方法一般執行在主線程(除非整個Rxjava代碼都寫在子線程,onSubscribe也會在子線程)
2.訂閱關係一旦生成,就回回調onSubscribe方法

3.調用source的subscribe方法,並將發射器傳遞過去

還記得source是怎麼來的嗎,是通過ObservableCreate的構造函數傳遞進來的

    public ObservableCreate(ObservableOnSubscribe<T> source) {
        this.source = source;
    }

由前面的推理可以知道,source就是Observable.create()方法的參數

new ObservableOnSubscribe< String>() {
            @Override
            public void subscribe(ObservableEmitter< String> e) throws Exception {
                e.onNext("事件1");
            }
        }

那source.subscribe(parent);就是回調了subscribe方法,拿到發射器然後調用發射器emitter的onNext方法發射“事件1”,由於發射器Emitter的onNext方法中調用了觀察者observer的onNext方法,所以事件直接回調到observer的onNext方法,完成事件的發送和監聽

總結(以create操作符爲例)

RxJava訂閱關係在ObservableCreate類中實現。先將被觀察者包裝成一個發射器,這時候就算訂閱完成了,執行observer.onSubscribe方法,然後調用source.subscribe方法,被觀察者拿到發射器發送事件,其實就是先調用e.onNext先揭開包裹,拿到觀察者observer,然後調用observer.onNext,完成。這裏發射器用到了裝飾模式。
再來張圖總結一下
在這裏插入圖片描述

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