RxJava2原始碼分析(二):操作符原理分析

wizardev發表於2019-01-19

前言:上一篇文章RxJava2原始碼分析(一):基本流程分析,是對RxJava2基本流程的分析,有了上一篇的基礎,這篇就再深入一點,開始分析一下RxJava2操作符的原理。

  為了方便理解RxJava2操作符的原理,這裡選擇最常用的map操作符來講解操作符的原理,示例程式碼如下

private void basicUseRxJava() {
        Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                emitter.onNext(1);
                emitter.onNext(2);
                emitter.onNext(3);
            }
        }).map(new Function<Integer, String>() {
            @Override
            public String apply(Integer integer) throws Exception {
                return "我是數字" + integer;
            }
        }).subscribe(new Observer<String>() {
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(String s) {
                Log.e("wizardev", "onNext: " + s);
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        });

    }
複製程式碼

內容回顧

  因為這一篇的內容是在上一篇的基礎上進行講解的,所以在講解操作符之前,先回顧一下前一篇主要的知識,如下:

  1. Observable執行的create方法後返回的是ObservableCreate例項。
  2. create方法的引數,實際是注入到ObservableCreate類中,作為它的成員變數。
  3. 呼叫Observable的subscribe方法最終呼叫的是ObservableCreate類中的subscribeActual方法。

操作符分析

  同樣,這裡分析原始碼的順序依然按照程式碼的執行順序,create方法前文已經分析過了,這裡就直接看map方法,map方法的程式碼如下

 public final <R> Observable<R> map(Function<? super T, ? extends R> mapper) {
        ObjectHelper.requireNonNull(mapper, "mapper is null");
        return RxJavaPlugins.onAssembly(new ObservableMap<T, R>(this, mapper));
    }
複製程式碼

有了前一篇的經驗,可以直接從這個方法中得出結論map方法返回的是ObservableMap例項,同時將map方法的引數及Observable自身注入了其構造方法中。

  現在看下ObservableMap類的原始碼,如下

public final class ObservableMap<T, U> extends AbstractObservableWithUpstream<T, U> {
    final Function<? super T, ? extends U> function;

    public ObservableMap(ObservableSource<T> source, Function<? super T, ? extends U> function) {
        super(source);//呼叫了其父類的構造方法
        this.function = function;
    }

    @Override
    public void subscribeActual(Observer<? super U> t) {
        source.subscribe(new MapObserver<T, U>(t, function));
    }
    //省略部分無關程式碼
    //...
}
複製程式碼

從上面的程式碼中可以看出,ObservableMap繼承至AbstractObservableWithUpstream,繼續進入AbstractObservableWithUpstream類中看下原始碼,如下

abstract class AbstractObservableWithUpstream<T, U> extends Observable<U> implements HasUpstreamObservableSource<T> {

    protected final ObservableSource<T> source;

    AbstractObservableWithUpstream(ObservableSource<T> source) {
        this.source = source;
    }

    @Override
    public final ObservableSource<T> source() {
        return source;
    }

}
複製程式碼

從上面的一段程式碼,可以知道AbstractObservableWithUpstream類其實就是Observable類的裝飾類,這個類的作用就是將例項化的Observable注入進來,作為其成員變數。分析到這裡可以得出這幾個類的關係如下

RxJava2原始碼分析(二):操作符原理分析

 注:ObservableMap中的成員變數function就是我們寫的這段程式碼

new Function<Integer, String>() {
            @Override
            public String apply(Integer integer) throws Exception {
                return "我是數字" + integer;
            }
        }
複製程式碼

好了,到這裡算是將map方法所做的事情分析完了,下面來看例項程式碼的最後一個方法subscribe.

subscribe方法分析

  通過上一篇文章可以知道subscribe方法實際呼叫的是Observable子類的subscribeActual方法,而這裡呼叫subscribe方法的類是ObservableMap,所以這裡呼叫的就是ObservableMap類的subscribeActual方法。現在來看下ObservableMap類的subscribeActual方法的原始碼,如下(為了分析方便,這裡將與subscribeActual方法有關的程式碼一起貼了出來)

final Function<? super T, ? extends U> function;

    public ObservableMap(ObservableSource<T> source, Function<? super T, ? extends U> function) {
        super(source);
        this.function = function;
    }

    @Override
    public void subscribeActual(Observer<? super U> t) {
        source.subscribe(new MapObserver<T, U>(t, function));
    }
複製程式碼

從上面的程式碼可以發現ObservableMap類的subscribeActual方法又呼叫了其上游的subscribe方法,為了便於理解這裡解釋一下文中所說的上游下游

文中說的“上游”及“下游”其實是相對而言的,這裡的“上游”是靠近Observable的,如示例程式碼中的subscribe是最下游,map是其上游,而map操作符又是crate方法的下游。

這裡上游的subscribe方法就是ObservableCreate呼叫的subscribe方法,實際就是呼叫ObservableCreate的subscribeActual方法,接著就是前一篇講過的流程了。

結論

  分析到現在可以得出以下結論

  • subscribe方法的呼叫流程是從下往上的,就是從下游往上游分別呼叫其subscribe方法。

為了方便理解,這裡我用時序圖表示subscribe的呼叫順序,如下圖

RxJava2原始碼分析(二):操作符原理分析

接收資料流程分析

  上面的內容分析了RxJava2基本流程加入操作符後的subscribe方法的執行順序,接著就來看下,資料的接收順序。經過上面的分析可以知道最終呼叫的是ObservableCreate類的subscribeActual方法,這裡與前一篇文章subscribeActual方法不同的就是subscribeActual方法的引數改變了,這裡的引數是MapObserver類的例項,再來看下ObservableCreate類的subscribeActual方法的原始碼,如下

//這裡的引數實際是MapObserver類的例項
protected void subscribeActual(Observer<? super T> observer) {
        CreateEmitter<T> parent = new CreateEmitter<T>(observer);
        observer.onSubscribe(parent);
        try {
            //這句程式碼的最終呼叫的就是MapObserver類的onNext方法。
            source.subscribe(parent);
        } catch (Throwable ex) {
            Exceptions.throwIfFatal(ex);
            parent.onError(ex);
        }
    }
複製程式碼

一些重要的內容已經在上面的程式碼中進行了註釋,可能這句source.subscribe(parent);程式碼,不好理解,這裡就來解釋一下這句程式碼,由上一篇文章可知,這裡的source就是示例程式碼中的new ObservableOnSubscribe<Integer>()...例項,這裡就是呼叫了這個例項的subscribe方法,而這個方法中的程式碼就是呼叫了其引數的onNext方法,**最終呼叫的就是MapObserver類的onNext方法。**現在,來看下MapObserver類的onNext方法的程式碼,如下

@Override
        public void onNext(T t) {
            if (done) {
                return;
            }

            if (sourceMode != NONE) {
                downstream.onNext(null);
                return;
            }

            U v;

            try {
            //1、
                v = ObjectHelper.requireNonNull(mapper.apply(t), "The mapper function returned a null value.");
            } catch (Throwable ex) {
                fail(ex);
                return;
            }
            //2、
            downstream.onNext(v);
        }
複製程式碼

主要來看下v = ObjectHelper.requireNonNull(mapper.apply(t), "The mapper function returned a null value.");這句程式碼,這句程式碼中的mapper就是注入到ObservableMap中的成員變數function,詳細內容可以檢視原始碼。呼叫的apply方法,就是示例程式碼中的這句程式碼

 @Override
            public String apply(Integer integer) throws Exception {
                return "我是數字" + integer;
            }
複製程式碼

接著,可以發現又呼叫了“2”處的程式碼downstream.onNext(v);,這句程式碼中的downstream就是示例程式碼中最下游的subscribe方法中的引數即是下面的程式碼

new Observer<String>() {
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(String s) {
                Log.e("wizardev", "onNext: " + s);
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        }
複製程式碼

所以這句downstream.onNext(v);呼叫的就是new Observer<String>()匿名類中的onNext方法。關於downstream的是何時初始化的,可以從MapObserver的父類BasicFuseableObserver類中知曉。

結論

  分析到這裡,又可以得出一些結論

  • 關於資料的處理上從上游到下游一級級的處理的。
  • 在MapObserver類中的onNext方法,首先呼叫的是function中的apply方法,然後再呼叫下游的onNext方法並將處理後的引數傳入。

總結

  通過分析map操作符,可以知道訂閱方法(subscribe)是從下游到上游進行訂閱的,而資料的發射是從上游到下游進行的。這兩個特性不僅僅是map操作符的特性,對其他的操作符同樣適用。為了講清楚這兩個特性,本文就選了比較具有代表性的map操作符,如果想了解其他操作符的原理,就順著這兩個特性分析就行了。

  授之以魚,不如授之以漁。本文的目的就是解釋清楚操作符的思想及原理,理解了這種思想及原理,分析其他的操作符也就不在話下了。

歡迎關注我的公眾號
掃碼關注公眾號,回覆“獲取資料”有驚喜

相關文章