RxJava 從入門到愛(ài)上它 - "變換"的深入理解

<a href="http://www.reibang.com/p/808b09d1b5ab">RxJava 從入門到愛(ài)上它 - 認(rèn)識(shí)</a>
<a href="http://www.reibang.com/p/f4af4752cd26">RxJava 從入門到愛(ài)上它 - 源碼分析線程控制</a>
關(guān)于Backpressure 作者也將在后續(xù)的文章中做出解析燕耿。

"變換"的理解(RxJava真正的核心)

RxJava中常用的"變換"

RxJava中的所有的操作 map自点、flatMapgroupBy跺株、scan苍日、concat等等 (這些操作方法的具體使用請(qǐng)看另一篇文章) 都是一種"變換"宅楞。為了更好地實(shí)現(xiàn)復(fù)雜的鏈?zhǔn)讲僮髡胱耍覀兙托枰獊?lái)好好解析下它的工作原理了。

RxJava"變換"的原理

這是map()的源碼(源碼版本為RxJava1.1.6)厌衙,其中調(diào)用了"變換"的核心方法left()距淫,我們先來(lái)分析下這段代碼:

    //Observable.java
    public final <R> Observable<R> map(Func1<? super T, ? extends R> func) {
        return lift(new OperatorMap<T迅箩, R>(func));
    }

    public final <R> Observable<R> lift(final Operator<? extends R溉愁, ? super T> operator) {
       return new Observable<R>(new OnSubscribeLift<T, R>(onSubscribe饲趋, operator));
    }

    //OnSubscribeLift.java
    @Override
    public void call(Subscriber<? super R> o) {
        try {
            Subscriber<? super T> st = hook.onLift(operator).call(o);
            try {
                // new Subscriber created and being subscribed with so 'onStart' it
                st.onStart();
                parent.call(st);
            } catch (Throwable e) {
                // localized capture of errors rather than it skipping all operators
                // and ending up in the try/catch of the subscribe method which then
                // prevents onErrorResumeNext and other similar approaches to error handling
                Exceptions.throwIfFatal(e);
                st.onError(e);
            }
        } catch (Throwable e) {
            Exceptions.throwIfFatal(e);
            // if the lift function failed all we can do is pass the error to the final Subscriber
            // as we don't have the operator available to us
            o.onError(e);
        }
    }

通過(guò)上面的源碼我們可以得知"變換"left()的流程如下(有些代碼沒(méi)有列出拐揭,此處不再贅述,感興趣的朋友可以去Github上詳細(xì)看下):
通過(guò)hook.onLift(operator)執(zhí)行封裝的操作奕塑,通過(guò)call()傳入原始Subscriber然后封裝成新的Subscriber堂污,然后通知父Observable來(lái)處理這個(gè)新的Subscriber

簡(jiǎn)述:

  1. 創(chuàng)建一個(gè)新的Observable(被觀察者)
    • 新的Observablecall()
      a. 通過(guò)Operator來(lái)創(chuàng)建一個(gè)新的Subscriber(觀察者)龄砰。
      b. 調(diào)用父Observablecall方法通知它對(duì)新創(chuàng)建的Subscriber進(jìn)行處理盟猖。

我們通過(guò)下面的一個(gè)例子來(lái)理解下整個(gè)鏈?zhǔn)讲僮鞯牧鞒蹋?/p>

Observable.just("hello"讨衣, "my", "name"式镐, "is"反镇, "nichool")
        .map(new Func1<String, String>() {
            @Override
            public String call(String s) {
                return "map: " + s;
            }
        })
        .map(new Func1<String娘汞, String>() {
            @Override
            public String call(String s) {
                return "map1: " + s;
            }
        })
        .subscribe(new Action1<String>() {
            @Override
            public void call(String s) {
                LogUtils.LogW(s);
            }
        });

先預(yù)想下將會(huì)打印的Log是什么4醪琛!.

上面的代碼可以分成下面這幾個(gè)流程:

執(zhí)行流程

執(zhí)行流程時(shí)序圖中(A)操作: 也就是剛才的left()的簡(jiǎn)述

時(shí)序圖(B)操作:Observable2.subscribe()將注冊(cè)的Subscriber傳入并調(diào)用call()你弦,開始通知流程

通知流程

通知流程時(shí)序圖中操作:
(C) : 調(diào)用Observable2.call() - ( 就是left()call方法)生成新的Subscriber subscriber2 然后調(diào)用Observable1.call();
(D) : 調(diào)用Observable1.call() - 生成 subscriber1惊豺,調(diào)用 Observable.call();
(E) : 調(diào)用Observable.call() - 將封裝了所有操作的subscriber1傳入call方法中,開始發(fā)送流程

發(fā)送流程

發(fā)送流程時(shí)序圖中操作:
(F) : 調(diào)用subscriber1 中的onNext 等方法
(I) : 調(diào)用subscriber2 中的onNext 等方法
(J) : 調(diào)用subscriber(此處為上面代碼中的subscribe()方法中的Subscriber) 中的onNext 等方法

整個(gè)流程合起來(lái)的流程圖 (圖片來(lái)自 https://gank.io/post/560e15be2dca930e00da1083#toc_15):

整合的流程圖

這是結(jié)果的Log

RxJavaDemo: map1: map: hello
RxJavaDemo: map1: map: my
RxJavaDemo: map1: map: name
RxJavaDemo: map1: map: is
RxJavaDemo: map1: map: nichool

總結(jié)

RxJava中"變換"的核心就是將操作封裝成新的觀察者禽作,多個(gè)”變換“的鏈?zhǔn)讲僮饕簿褪嵌鄠€(gè)觀察者與被觀察者相互通知與處理的流程尸昧,整個(gè)RxJava項(xiàng)目通過(guò)這種代理的思想來(lái)實(shí)現(xiàn)復(fù)雜的邏輯。(真心厲害?醭ァE胨住!)

本文的分析將非常有助于線程調(diào)度方面的理解@晖薄衷蜓!
分析過(guò)程中如若存在錯(cuò)誤,請(qǐng)?jiān)谙路皆u(píng)論處給予指正尘喝。

↓↓↓↓↓如果覺(jué)得可以的話,請(qǐng)點(diǎn)擊下面的喜歡斋陪⌒嗤剩或者打賞哦,我會(huì)更加努力的无虚〉拊↓↓↓↓↓

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市友题,隨后出現(xiàn)的幾起案子嗤堰,更是在濱河造成了極大的恐慌,老刑警劉巖度宦,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件踢匣,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡戈抄,警方通過(guò)查閱死者的電腦和手機(jī)离唬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)划鸽,“玉大人输莺,你說(shuō)我怎么就攤上這事戚哎。” “怎么了嫂用?”我有些...
    開封第一講書人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵型凳,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我嘱函,道長(zhǎng)啰脚,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任实夹,我火速辦了婚禮橄浓,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘亮航。我一直安慰自己荸实,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開白布缴淋。 她就那樣靜靜地躺著准给,像睡著了一般。 火紅的嫁衣襯著肌膚如雪重抖。 梳的紋絲不亂的頭發(fā)上露氮,一...
    開封第一講書人閱讀 51,562評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音钟沛,去河邊找鬼畔规。 笑死,一個(gè)胖子當(dāng)著我的面吹牛恨统,可吹牛的內(nèi)容都是我干的叁扫。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼畜埋,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼莫绣!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起悠鞍,我...
    開封第一講書人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤对室,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后咖祭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體掩宜,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年心肪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了锭亏。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡硬鞍,死狀恐怖慧瘤,靈堂內(nèi)的尸體忽然破棺而出戴已,到底是詐尸還是另有隱情罗侯,我是刑警寧澤狐蜕,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布,位于F島的核電站贷币,受9級(jí)特大地震影響怔匣,放射性物質(zhì)發(fā)生泄漏握联。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一每瞒、第九天 我趴在偏房一處隱蔽的房頂上張望金闽。 院中可真熱鬧,春花似錦剿骨、人聲如沸代芜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)挤庇。三九已至,卻和暖如春贷掖,著一層夾襖步出監(jiān)牢的瞬間嫡秕,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工苹威, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留昆咽,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓屠升,卻偏偏與公主長(zhǎng)得像潮改,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子腹暖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

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