RxJava源碼分析之變換

RxJava 簡(jiǎn)單來(lái)說(shuō) , 是一個(gè)很靈活切換線程的褲子 .

  • 簡(jiǎn)單試?yán)?/li>
  • 源碼解讀試?yán)?/li>
  • 變換思想圖解
  • 變換思想總結(jié)

1 、 簡(jiǎn)單試?yán)?/h3>
    
    Observable.just("url")//
        .map(new Function<String, Long>() {
            @Override
            public Long apply(@NonNull String s) throws Exception {
                return 1l;
            }
        })

        .map(new Function<Long, Integer>() {
            @Override
            public Integer apply(@NonNull Long l) throws Exception {
                return 50;
            }
        })
         .subscribe(new Observer<Integer>() {
             @Override
             public void onSubscribe(@NonNull Disposable d) {

             }

             @Override
             public void onNext(@NonNull Integer integer) {

                 Log.i("Info","onNext:"+integer);

             }

             @Override
             public void onError(@NonNull Throwable e) {

                 Log.i("Info","異常:"+e.getLocalizedMessage());
                 e.printStackTrace();
             }

             @Override
             public void onComplete() {

             }
         });
         
         打印:nNext:50
    

2 、 源碼解讀實(shí)例

創(chuàng)建 ObservableJust 對(duì)象

    
    public static <T> Observable<T> just(T item) {
        ObjectHelper.requireNonNull(item, "The item is null");
         //這里其實(shí)是直接返回ObservableJust對(duì)象 . 
        return RxJavaPlugins.onAssembly(new ObservableJust<T>(item));
    }
    
     public static <T> Observable<T> onAssembly(@NonNull Observable<T> source) {
            //默認(rèn)情況下 onObservableAssembly 為空 , 需要全局傳入
        Function<? super Observable, ? extends Observable> f = onObservableAssembly;
        if (f != null) {
            return apply(f, source);
        }
        return source;

    }

RxJavaPlugins.onAssembly 這里起到了 Hook 作用 , 加多了一層 , 可以用于 Fliter 例如

RxJavaPlugins.setOnObservableAssembly(new Function<Observable, Observable>() {


            @Override
            public Observable apply(@NonNull Observable observable) throws Exception {
                     Log.i("Info","Hook  創(chuàng)建對(duì)象 Observable ");
                if(observable instanceof ObservableJust && !((((ObservableJust)(observable)).call()) instanceof String) ){

                    return null;
                }
                return observable;
            }
        });
        
        //再一次運(yùn)行上面的例子就是打印出:Hook  創(chuàng)建對(duì)象 Observable 

使得所有屬于全局 ObservableJust 的 value 非 String 類型都無(wú)法正常創(chuàng)建 . 下面進(jìn)入重點(diǎn)變換
變換也是一樣加了一層全局 Hook . 這里直接默認(rèn)返回 new ObservableMap<T, R>(this, mapper)即可

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));
    }
    

ObservableMap 也是 Observable 的一個(gè)子類 , 把 ObservableJust 和 變換函數(shù) Function 傳進(jìn)去創(chuàng)建 ObservableMap , 下一個(gè) ObservableMap 走相同邏輯 , 這樣就形成 ObservableJust(1) ∈ ObservableMap(2)
∈ ObservableMap(3) 的關(guān)系 (∈屬于) 典型的責(zé)任鏈模式 . 上面例子邏輯走到 ···(A).subscribe(new Observer<Integer>()··· (A)處的對(duì)象為ObservableMap(3) , 發(fā)生訂閱 . 繼續(xù)查看源碼

public final void subscribe(Observer<? super T> observer) {
                        ···· 省略N多邏輯
                    subscribeActual(observer);

subscribeActual是一個(gè)抽象方法 , 查看子類 ObservableMap 實(shí)現(xiàn)該方法

public void subscribeActual(Observer<? super U> t) {
            //這里的source為ObservableMap(2)對(duì)象
        source.subscribe(new MapObserver<T, U>(t, function));

    }

source 調(diào)用 subscribe 跟 ObservableMap(3) 執(zhí)行相同邏輯 , 這里的 source 指的是 ObservableMap(2) 對(duì)象 , 這樣就形成了(有序序列). MainActivity 里的 內(nèi)部類 Observer 被包裝了一層 MapObserver 當(dāng)成參數(shù)往上傳形成了鏈表 MapObserver(3) --> MapObserver(2) --> Observer(1) .

最終回到 ObservableJust 發(fā)生訂閱把數(shù)據(jù)源于流的形式一層一層發(fā)射 , 見

//ObservableJust 的subscribeActual 方法
protected void subscribeActual(Observer<? super T> s) {
        Log.i("Info","subscribeActual 發(fā)射 ");
        //這里的s 是MapObserver(3)對(duì)象
        ScalarDisposable<T> sd = new ScalarDisposable<T>(s, value);
        //observer 的 onSubscribe 方法被回調(diào)
        s.onSubscribe(sd);
        sd.run();

    }
    
    public void run() {
            if (get() == START && compareAndSet(START, ON_NEXT)) {
                    //正式發(fā)射數(shù)據(jù)源
                observer.onNext(value);
                if (get() == ON_NEXT) {
                    lazySet(ON_COMPLETE);
                    observer.onComplete();
                }
            }
        }

數(shù)據(jù)源發(fā)射 MapObserver(3).onNext() --(Function變換)--> MapObserver(2).onNext() --(Function 變換)-->Observer(1).onNext() .

3 件缸、 變換思想圖解

p.png

說(shuō)明 : subscribe 是發(fā)生在 Observable 里面調(diào)用subscribeActual , 內(nèi)部創(chuàng)建 MapObserver 包裝對(duì)象 Observer , 傳給父級(jí)Observable . source.subscribe(new MapObserver<T, U>(t, function));

4、 變換思想總結(jié).

變換是 RxJava 最核心思想 , RxJava 源碼比較繞 , 但是萬(wàn)變不離其中 , 包括線程調(diào)度 subscribeOn() 和 observeOn() 也是利用變換 .

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末茧痕,一起剝皮案震驚了整個(gè)濱河市句葵,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌廊遍,老刑警劉巖嬉愧,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異喉前,居然都是意外死亡没酣,警方通過(guò)查閱死者的電腦和手機(jī)王财,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)裕便,“玉大人绒净,你說(shuō)我怎么就攤上這事〕ニィ” “怎么了疯溺?”我有些...
    開封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)哎垦。 經(jīng)常有香客問(wèn)我囱嫩,道長(zhǎng),這世上最難降的妖魔是什么漏设? 我笑而不...
    開封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任墨闲,我火速辦了婚禮,結(jié)果婚禮上郑口,老公的妹妹穿的比我還像新娘鸳碧。我一直安慰自己,他們只是感情好犬性,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開白布瞻离。 她就那樣靜靜地躺著,像睡著了一般乒裆。 火紅的嫁衣襯著肌膚如雪套利。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天鹤耍,我揣著相機(jī)與錄音肉迫,去河邊找鬼。 笑死稿黄,一個(gè)胖子當(dāng)著我的面吹牛喊衫,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播杆怕,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼族购,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了陵珍?” 一聲冷哼從身側(cè)響起寝杖,我...
    開封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎撑教,沒(méi)想到半個(gè)月后朝墩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體醉拓,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡伟姐,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年收苏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片愤兵。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鹿霸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出秆乳,到底是詐尸還是另有隱情懦鼠,我是刑警寧澤,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布屹堰,位于F島的核電站肛冶,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏扯键。R本人自食惡果不足惜睦袖,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望荣刑。 院中可真熱鬧馅笙,春花似錦、人聲如沸厉亏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)爱只。三九已至皿淋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間恬试,已是汗流浹背沥匈。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留忘渔,地道東北人高帖。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像畦粮,于是被迫代替她去往敵國(guó)和親散址。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容