Rxjava 過(guò)程分析一之簡(jiǎn)易流程

Rxjava 過(guò)程分析一

說(shuō)明

  • 該文章是基于 Rxjava2 源碼牙言。
  • 該篇只是講述 Rxjava 建議的用法掸犬,不涉及操作符和線(xiàn)程切換聋伦, 后兩個(gè)會(huì)有新的篇幅去寫(xiě)。 一步一步的來(lái)蛉拙。
  • 在源碼中那些判空還有 Rxjava 中 RxJavaPlugins 鉤子等在分析中去除(只關(guān)注用法和思想尸闸, 和主流程不管的暫時(shí)剔除)。
  • 由于習(xí)慣孕锄, 和 Rxjava2 中的命名吮廉。 我稱(chēng) emitter 為上游, 也就是發(fā)射水(數(shù)據(jù))的源頭畸肆, 結(jié)果回調(diào)給外部的 FlowableSubscriber宦芦, 我稱(chēng)它為下游。 上游流水流到下游轴脐!

最簡(jiǎn)單的使用

Flowable.create(new FlowableOnSubscribe<String>() {
    @Override
    public void subscribe(FlowableEmitter<String> emitter) throws Exception {
         // emitter.onNext("");
        // emitter.onError();
       // emitter.onComplete();
    }
}, BackpressureStrategy.LATEST).subscribe(new FlowableSubscriber<String>() {
    @Override
    public void onSubscribe(Subscription s) {
    }
    @Override
    public void onNext(String s) {
    }
    @Override
    public void onError(Throwable t) {
    }
    @Override
    public void onComplete() {
    }
});

引發(fā)的思考

  1. 調(diào)用 emitter 的 onNext调卑、 onError抡砂、 onComplete, 就會(huì)回調(diào) FlowableSubscriber 中對(duì)應(yīng)的方法恬涧。 那么這兩個(gè)對(duì)象是一個(gè)嗎注益? 有什么聯(lián)系呢?
  2. 我們把上述代碼寫(xiě)好后溯捆, 會(huì)自動(dòng)調(diào)用并回調(diào)丑搔, 那么上游發(fā)射器 emitter 是什么時(shí)候觸發(fā)的呢? 該方法是什么時(shí)機(jī)和誰(shuí)調(diào)用的呢提揍?

源碼分析

從創(chuàng)建開(kāi)始

 public static <T> Flowable<T> create(FlowableOnSubscribe<T> source, BackpressureStrategy mode) {
    return new FlowableCreate<T>(source, mode);
}

簡(jiǎn)單嗎大兄弟啤月, 僅僅是創(chuàng)建了一個(gè) FlowableCreate 類(lèi)而已。 并對(duì)成員變量賦值劳跃。

簡(jiǎn)單說(shuō)說(shuō)下游

在開(kāi)發(fā)中顽冶, 可能很多都有在用回調(diào)吧。 再次機(jī)會(huì)我也想說(shuō)說(shuō)回調(diào)是咋回事售碳。 其實(shí) java 中的常用的內(nèi)部類(lèi)回調(diào)强重, 還是 c 的函數(shù)指針, 或者其語(yǔ)言的閉包(swift), 其實(shí)不要把它們想的多么神奇贸人。 就這么想间景, 我把一個(gè)實(shí)例地址或者函數(shù)地址給你了, 你在內(nèi)部去調(diào)用我的方法艺智, 自然就運(yùn)行到了外面了倘要。

訂閱

 public final void subscribe(FlowableSubscriber<? super T> s) {
    try {
        Subscriber<? super T> z = s;
        subscribeActual(z);
    } catch (NullPointerException e) { 
        throw e;
    } catch (Throwable e) {

    }
}

信息量很少, 只是調(diào)用了當(dāng)前 Flowable 的 subscribeActual() 方法十拣。 我們前面知道當(dāng)前的 Flowable 是 FlowableCreate 對(duì)象封拧, 所以進(jìn) FlowableCreate 中去看看做了什么事情。

 public void subscribeActual(Subscriber<? super T> t) {
    BaseEmitter<T> emitter;

    switch (backpressure) {
    case MISSING: {
        emitter = new MissingEmitter<T>(t);
        break;
    }
    case ERROR: {
        emitter = new ErrorAsyncEmitter<T>(t);
        break;
    }
    case DROP: {
        emitter = new DropAsyncEmitter<T>(t);
        break;
    }
    case LATEST: {
        emitter = new LatestAsyncEmitter<T>(t);
        break;
    }
    default: {
        emitter = new BufferAsyncEmitter<T>(t, bufferSize());
        break;
    }
    }

    t.onSubscribe(emitter);
    try {
        source.subscribe(emitter);
    } catch (Throwable ex) {
        Exceptions.throwIfFatal(ex);
        emitter.onError(ex);
    }
}

我們這里不去討論背壓等問(wèn)題夭问, 所以我們只是關(guān)注主要流程和關(guān)鍵方法泽西。 其中一眼就可以看到關(guān)鍵的一個(gè)就是在 try 塊中的 source.subscribe(emitter); source 是什么呀? 就是我們?cè)?new FlowableCreate 傳進(jìn)來(lái)的 Flowable.create(new FlowableOnSubscribe<String>()) 中 FlowableOnSubscribe 對(duì)象缰趋。 source 的 subscribe 這不就是運(yùn)行了 外部 FlowableOnSubscribe 的 subscribe嘛捧杉, 所以外部調(diào)用 onNext, onError, onComplete 方法, 其實(shí)調(diào)用了 內(nèi)部 emitter 中對(duì)應(yīng)的方法秘血。 我們以背壓為 LATEST 為例看看 LatestAsyncEmitter 被調(diào)用的方法做了什么事情味抖。 先多說(shuō)一句, 初始化 emitter 時(shí)我們傳入的是下游哦灰粮, 下游相應(yīng)的方法調(diào)用了仔涩, 那么外部的就會(huì)看似回調(diào)出去拿到結(jié)果了!

我們以 onNext 為例粘舟, 看看 LatestAsyncEmitter 被調(diào)用到 onNext 做了什么事情熔脂。

 public void onNext(T t) {
    queue.set(t);
    drain();
}

看到是先把結(jié)果存到了隊(duì)列中佩研, 我們不考慮背壓, 所以我們看主要的大致流程哈锤悄。 顯然下一個(gè)有用的代碼就是 drain() 了韧骗。

 void drain() {
    final Subscriber<? super T> a = downstream;
    final AtomicReference<T> q = queue;
        // ......
        T o = q.getAndSet(null);
        // ......
        a.onNext(o);
        // ......
}

其中 downstream 就是我們外部的 FlowableSubscriber 及下游了嘉抒。 我們可以看到零聚, 簡(jiǎn)單的從隊(duì)列中取出數(shù)據(jù), 直接調(diào)用了下游的 onNext些侍。 就這樣數(shù)據(jù)就被從上游流向了下游隶症。

前面的疑惑問(wèn)題

  • 上游和下游是一個(gè)東西嗎? 它們的關(guān)系是什么岗宣?

這個(gè)問(wèn)題從上面的分析已經(jīng)很明顯了蚂会。 上游和下游不是一個(gè)東西, 上游 emitter 調(diào)用相應(yīng)的方法去回調(diào)下游的方法耗式。

  • 在哪一個(gè)時(shí)刻觸發(fā)的事件流動(dòng)呢胁住?

其實(shí)是在上游 emitter 調(diào)用相應(yīng)的方法那一刻, 比如調(diào)用 onNext刊咳。 那么是在哪一個(gè)時(shí)機(jī)觸發(fā)調(diào)用的呢彪见? 很明顯是在訂閱時(shí), 調(diào)用了 subscribeActual 中又調(diào)用了上游的 subscribe(emitter) 觸發(fā)了數(shù)據(jù)的流動(dòng)娱挨。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末余指,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子跷坝,更是在濱河造成了極大的恐慌酵镜,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,591評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件柴钻,死亡現(xiàn)場(chǎng)離奇詭異淮韭,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)贴届,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)缸濒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人粱腻,你說(shuō)我怎么就攤上這事庇配。” “怎么了绍些?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,823評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵捞慌,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我柬批,道長(zhǎng)啸澡,這世上最難降的妖魔是什么袖订? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,204評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮嗅虏,結(jié)果婚禮上洛姑,老公的妹妹穿的比我還像新娘。我一直安慰自己皮服,他們只是感情好楞艾,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著龄广,像睡著了一般硫眯。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上择同,一...
    開(kāi)封第一講書(shū)人閱讀 51,190評(píng)論 1 299
  • 那天两入,我揣著相機(jī)與錄音,去河邊找鬼敲才。 笑死裹纳,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的紧武。 我是一名探鬼主播剃氧,決...
    沈念sama閱讀 40,078評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼脏里!你這毒婦竟也來(lái)了她我?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,923評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤迫横,失蹤者是張志新(化名)和其女友劉穎嚣潜,沒(méi)想到半個(gè)月后口猜,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體畅姊,經(jīng)...
    沈念sama閱讀 45,334評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鸵钝,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了呛讲。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片禾怠。...
    茶點(diǎn)故事閱讀 39,727評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖贝搁,靈堂內(nèi)的尸體忽然破棺而出吗氏,到底是詐尸還是另有隱情,我是刑警寧澤雷逆,帶...
    沈念sama閱讀 35,428評(píng)論 5 343
  • 正文 年R本政府宣布弦讽,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏往产。R本人自食惡果不足惜被碗,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望仿村。 院中可真熱鬧锐朴,春花似錦、人聲如沸蔼囊。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,672評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)压真。三九已至娩嚼,卻和暖如春蘑险,著一層夾襖步出監(jiān)牢的瞬間滴肿,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,826評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工佃迄, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留泼差,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,734評(píng)論 2 368
  • 正文 我出身青樓呵俏,卻偏偏與公主長(zhǎng)得像堆缘,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子普碎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評(píng)論 2 354

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