RxSwift 源碼解析03:Observable 核心邏輯

本文主要分析 Observable 核心邏輯

Observable 三部曲

  • 序列三部曲:序列產(chǎn)生、訂閱、銷毀
  • 但是在實(shí)際代碼中,如下所示,觀察序列的整個(gè)流程是
    • 創(chuàng)建觀察序列
    • 訂閱信號(hào)(訂閱觀察)
    • 發(fā)送信號(hào)(發(fā)送事件)
    • 銷毀觀察序列
//1、創(chuàng)建序列
let ob = Observable<Any>.create { observer **in**
    //3、發(fā)送信號(hào)
    observer.onNext("發(fā)送信號(hào)")
    //error 和 complete 二選一
    //observer.onError(NSError.init(domain: "myError", code: 10010, userInfo: nil))
    observer.onCompleted()
    return Disposables.create()
}

//2、訂閱信號(hào)
ob.subscribe { text **in**
    print("訂閱到了: \(text)")
} onError: { error **in**
    print("error \(error)")
} onCompleted: {
    print("完成")
} onDisposed: {
    print("銷毀")
}

.disposed(by: disposeBag)

//--------打印---------
訂閱到了: 發(fā)送信號(hào)
完成
銷毀

RxSwift的響應(yīng)式核心邏輯類似于iOS中的UI事件響應(yīng)

  • UIControl類調(diào)用addTarget響應(yīng)#selector定義的事件
  • RxSwift 將響應(yīng)事件留在 rx內(nèi)部類進(jìn)行處理
  • 在內(nèi)部類由訂閱中心執(zhí)行onNext發(fā)送消息
  • 消息傳送到subscribe接收

這里需要重點(diǎn)關(guān)注的是

  • 1、序列的創(chuàng)建方法 create() 中的閉包是什么時(shí)候執(zhí)行的?
  • 2、訂閱信號(hào) subscribe() 中的閉包是什么時(shí)候執(zhí)行的?
  • 3、信號(hào)從發(fā)送到接收的流程是怎樣的?

下面我們帶著這些問題來一一探索

RxSwift 核心邏輯分析

主要分三步進(jìn)行分析

  • 創(chuàng)建序列 create()
  • 訂閱信號(hào) subscribe()
  • 發(fā)送信號(hào) onNext()

創(chuàng)建序列 create()

  • 進(jìn)入create 函數(shù)源碼,其中是創(chuàng)建一個(gè) AnonymousObservable 對(duì)象,AnonymousObservable 是匿名可觀察序列

    create_01.png

  • 進(jìn)入 AnonymousObservable 類,這個(gè)類主要用來存儲(chǔ)產(chǎn)生事件的閉包(self.subscribeHandler = subscribeHandler)和 激活事件閉包的入口函數(shù) run()

    create_02.png

  • 查看 AnonymousObservable的繼承鏈:AnonymousObservable ---> Producer 生產(chǎn)者 --> Observable --> 遵循 ObservableType 協(xié)議 --> 遵循 ObservableConvertibleType 協(xié)議

    • ObservableConvertibleType 是一個(gè)協(xié)議,有一個(gè)關(guān)聯(lián)類型(用于定義任意類型的序列,即創(chuàng)建序列時(shí)傳入的類型Any),和函數(shù) asObservable() (可將非序列對(duì)象轉(zhuǎn)化為序列對(duì)象)
      create_03.png
    • ObservableType 是一個(gè)協(xié)議,提供一個(gè)基本功能:訂閱信號(hào)


      create_04.png
    • Observable 是可觀察序列,有兩個(gè)函數(shù),分別是 subscribe方法(無具體實(shí)現(xiàn))、asObservable函數(shù)(返回一個(gè) Observable 序列對(duì)象)


      create_05.png
    • Producer 生產(chǎn)者類(工廠設(shè)計(jì)模式),有兩個(gè)函數(shù):subscribe(訂閱的具體實(shí)現(xiàn),后面會(huì)講解) 和 run(無具體實(shí)現(xiàn))


      create_06.png

****create() 創(chuàng)建序列總結(jié)**

  • 從create()的源碼中,可以看出創(chuàng)建序列的過程中,主要是保存了一個(gè)產(chǎn)生事件的閉包 subscribeHandler

  • AnonymousObservable 繼承鏈:AnonymousObservable ---> Producer 生產(chǎn)者 --> Observable --> 遵循 ObservableType 協(xié)議 --> 遵循 ObservableConvertibleType 協(xié)議

    • ObservableConvertibleType:關(guān)聯(lián)類型 Element + 函數(shù) asObservable()
    • ObservableType:函數(shù) subscribe()
    • Observable(可觀察序列):函數(shù) subscribe() + 函數(shù) asObservable()
    • Producer(生產(chǎn)者):函數(shù) subscribe() + 函數(shù) run()
    • AnonymousObservable(匿名可觀察序列):產(chǎn)生事件閉包 subscribeHandler + 函數(shù) run()
  • create() 創(chuàng)建序列流程

    • 創(chuàng)建 AnonymousObservable 匿名可觀察序列 A,
    • A 保存發(fā)送信號(hào)的閉包,即產(chǎn)生事件的閉包(subscribeHandler)

訂閱序列 subscribe()

  • 進(jìn)入 subscribe() 源碼

    • 創(chuàng)建 AnonymousObserver 匿名訂閱者(觀察者)對(duì)象
    • 將訂閱回調(diào)閉包保存在 AnonymousObserver 的屬性 eventHandler
    • 關(guān)鍵代碼是 self.asObservable().subscribe(observer),其中 asObservable 是返回一個(gè)序列對(duì)象本身,然后調(diào)用 subscribe 將 AnonymousObserver匿名觀察者對(duì)象傳遞過去
      subscribe_07.png
  • 為了確認(rèn) self.asObservable() 的類型,可以通過斷點(diǎn)調(diào)試確認(rèn)為 ,這里是一個(gè) AnonymousObservable 匿名可觀察序列對(duì)象


    subscribe_08.png
  • 查找 AnonymousObservable 類的 subscribe 方法,但是這個(gè)類中并沒有這個(gè)函數(shù),這個(gè)類的繼承鏈為:AnonymousObservable --> ObserverBase --> 遵循 Disposable、ObserverType 協(xié)議

    • Disposable 是一個(gè)銷毀協(xié)議,其中只有一個(gè)方法 dispose() 銷毀方法


      subscribe_11.png
    • ObserverType 是一個(gè)觀察者協(xié)議,有關(guān)聯(lián)類型、on方法


      subscribe_12.png
    • ObserverBase 觀察者基類,具備發(fā)送響應(yīng)和銷毀的功能


      subscribe_13.png
    • AnonymousObserver 匿名觀察者類,主要用來保存事件響應(yīng)閉包,以及發(fā)送響應(yīng)、銷毀等功能


      subscribe_14.png
  • AnonymousObservable 的父類 Producer 中查找,其源碼如下

    • 從源碼中發(fā)現(xiàn),subscribe 中調(diào)用了 AnonymousObservablerun 函數(shù),將 observer 訂閱者作為參數(shù)傳了進(jìn)來
      subscribe_09.png
  • 進(jìn)入 AnonymousObservable 類的 run 實(shí)現(xiàn)

    • 首先創(chuàng)建了一個(gè) AnonymousObservableSink 對(duì)象,即管道對(duì)象,并持有 observer(訂閱者/觀察者對(duì)象)、cancel(銷毀者對(duì)象)
    • 然后調(diào)用 AnonymousObservableSink 的 run函數(shù),將 self(AnonymousObservable 匿名觀察序列對(duì)象)作為參數(shù)傳遞過去
    • AnonymousObservableSink 類的主要作用就是鏈接 可觀察者Observable觀察者Observer,實(shí)現(xiàn)事件的傳遞,起到一個(gè)橋梁/通道的作用
      subscribe_10.png
  • 進(jìn)入 AnonymousObservableSink 類的 run 實(shí)現(xiàn)

    • 這里的parent 就是傳入的self,即 AnonymousObservable
    • subscribeHandler 是create函數(shù)產(chǎn)生的閉包,到這里我們解決了第一個(gè)疑問:create()的閉包什么時(shí)候執(zhí)行
      subscribe_15.png
    • run中的 selfAnonymousObservableSink對(duì)象,簡單理解就是將 AnonymousObservableSink對(duì)象 轉(zhuǎn)換為 AnyObserver對(duì)象,那具體是如何轉(zhuǎn)換的呢?
  • 進(jìn)入 AnyObserver 的源碼,AnyObserver是一個(gè)結(jié)構(gòu)體,查看其第二個(gè) init 方法,將 AnonymousObservableSink 的on函數(shù)賦值給了 AnyObserver 的observer屬性,所以 self.observer 是一個(gè)函數(shù) 即on函數(shù)。所以 AnonymousObservableSink 中 run 函數(shù)中的 AnyObserver(self) 其實(shí)就是 create閉包中的參數(shù) observer

    subscribe_16.png

    • 由于AnonymousObservable 是匿名類,僅內(nèi)部使用,不暴露給外部,所以需要通過 AnyOberver 來調(diào)用 onNext等
    • AnyOberver 類遵循 ObserverType 協(xié)議,所以可以調(diào)用 onNext函數(shù),此時(shí) onNext函數(shù) 實(shí)現(xiàn)中的 on 就是 【AnyObserver - observer - on 函數(shù)塊】中通過 observer保存的函數(shù)塊
      subscribe_21.png
    • 這里就解釋了 為什么發(fā)送信號(hào)的代碼 observer.onNext("發(fā)送信號(hào)") 最終會(huì)觸發(fā) AnonymousObservableSink.on事件了
  • 進(jìn)入 AnonymousObservableSinkon 函數(shù),將event分解成不同的事件

    subscribe_17.png

  • 查找 AnonymousObservableSink 類的 forwardOn 函數(shù)實(shí)現(xiàn),子類未找到,在其父類 Sink中找到了,源碼如下

    • 這里的 observer 是 外部調(diào)用 subscribe() 函數(shù),其內(nèi)部生成的 AnonymousObserver 匿名觀察者對(duì)象
      subscribe_18.png
  • 查找 AnonymousObserver 的 on 函數(shù),未找到,在其父類 ObserverBase 中查找,實(shí)現(xiàn)如下

    • 內(nèi)部調(diào)用了 onCore 函數(shù),父類中是抽象方法,沒有具體實(shí)現(xiàn)


      subscribe_19.png
    • 查找 AnonymousObserveronCore 函數(shù)實(shí)現(xiàn),這里的 eventHandler 就是 調(diào)用subscribe 函數(shù)傳入的閉包,到此就可以理解第三個(gè)問題 :subscribe 的閉包是什么時(shí)候調(diào)用的了。同時(shí)也將 創(chuàng)建的閉包和訂閱的閉包進(jìn)行了關(guān)聯(lián)。
      subscribe_20.png

**subscribe() 訂閱信號(hào)(訂閱序列)總結(jié)

  • AnonymousObserver 繼承鏈:AnonymousObservable --> ObserverBase --> 遵循 Disposable、ObserverType 協(xié)議

    • Disposable:函數(shù) dispose()
    • ObserverType:關(guān)聯(lián)類型 Element + 函數(shù) on()
    • ObserverBase(觀察者基類):函數(shù) on() + 函數(shù) onCore() + 函數(shù) dispose()
    • AnonymousObservable(匿名觀察者):事件回調(diào)閉包 eventHandler + 函數(shù) onCore()
  • subscribe() 訂閱信號(hào)(訂閱序列)流程

    • 創(chuàng)建 AnonymousObserver匿名觀察者 B,保存訂閱信號(hào)的閉包,即事件回調(diào)閉包(eventHandler)
    • A 對(duì)象調(diào)用函數(shù) asObservable() 轉(zhuǎn)換為序列對(duì)象,序列調(diào)用函數(shù) subscribe,將 B 傳遞過去,即 A.asObservable().subscribe(B) 等價(jià)于 A.subscribe(B)
    • 查找函數(shù) subscribe() 實(shí)現(xiàn),AnonymousObservable類中沒有,從其父類 Producer 中找到,其中調(diào)用了 AnonymousObservablerun() 函數(shù),將 B 作為參數(shù)傳遞,即 A.run(B)
    • 進(jìn)入函數(shù) run() 的源碼,創(chuàng)建了一個(gè) AnonymousObservableSink 通道對(duì)象,并持有 observer(觀察者)、cancel(銷毀者),同時(shí)調(diào)用了 AnonymousObservableSink 的函數(shù) run(),即 AnonymousObservableSink.run(A)
    • 進(jìn)入 AnonymousObservableSink類的函數(shù) run() 源碼, AsubscribeHandler 閉包回調(diào),并傳入一個(gè) AnyObserver 對(duì)象,即 A.subscribeHandler(sink)
      • 這里是將 AnonymousObservableSink 轉(zhuǎn)換為 AnyObserver 對(duì)象,并將 sink 的函數(shù) on() 賦值給了 AnyObserver 的屬性 observer(是一個(gè) on 函數(shù)), AnyObserver(self) 等價(jià)于 create()閉包中的參數(shù) ,即AnyObserver.observer = AnonymousObservableSink.on = create的閉包參數(shù) observer
    • 進(jìn)入 AnonymousObservableSink 的函數(shù) on() 的實(shí)現(xiàn),這里將 event 分解成了不同的事件,并調(diào)用 AnonymousObservableSink 的函數(shù) forwardOn(),即 AnonymousObservableSink.on() --> AnonymousObservableSink.forwardOn()
    • 進(jìn)入 AnonymousObservableSink 的函數(shù) forwardOn()實(shí)現(xiàn),其具體實(shí)現(xiàn)在父類 Sink 中,調(diào)用了 AnonymousObserver 的函數(shù) on(),即 AnonymousObservableSink.forwardOn() --> AnonymousObserver.on()
    • 進(jìn)入AnonymousObserver 的函數(shù) on(),其具體實(shí)現(xiàn)在父類 ObserverBase 中,調(diào)用了 AnonymousObserver 的函數(shù) onCore(),即 AnonymousObserver.on() --> AnonymousObserver.onCore()
    • 進(jìn)入 AnonymousObserver 的函數(shù) onCore() 的實(shí)現(xiàn),BeventHandler 閉包回調(diào),即 B.eventHandler(event)

發(fā)送信號(hào) onNext()

  • 會(huì)走到創(chuàng)建 B 的回調(diào)閉包中發(fā)送信號(hào)
    onNext_22.png
  • 然后接著走函數(shù) subscribe() 訂閱信號(hào)的流程

發(fā)送信號(hào) onNext()

  • 會(huì)走到創(chuàng)建 B 的回調(diào)閉包中發(fā)送信號(hào)
  • 然后接著走函數(shù) subscribe() 訂閱信號(hào)的流程

總結(jié)

創(chuàng)建 - 訂閱 - 發(fā)送信號(hào)整體流程圖

整體流程圖.png

其核心邏輯思維導(dǎo)圖

核心邏輯.png
  • create() 創(chuàng)建序列

    • 創(chuàng)建 AnonymousObservable 匿名可觀察序列 A,
    • 保存發(fā)送信號(hào)的閉包,即 A.subscribeHandler = subscribeHandler
  • subscribe() 訂閱信號(hào)(訂閱序列)

    • 創(chuàng)建 AnonymousObserver匿名觀察者 B,
    • 保存訂閱信號(hào)的閉包,即 B.eventHandler = eventHandler
    • A 對(duì)象調(diào)用函數(shù) asObservable() 轉(zhuǎn)換為序列對(duì)象,序列調(diào)用函數(shù) subscribe,將 B 傳遞過去,即 A.asObservable().subscribe(B) 等價(jià)于 A.subscribe(B)
    • 查找函數(shù) subscribe() 實(shí)現(xiàn),AnonymousObservable類中沒有,從其父類 Producer 中找到,其中調(diào)用了 AnonymousObservablerun() 函數(shù),將 B 作為參數(shù)傳遞,即 A.run(B)
    • 進(jìn)入函數(shù) run() 的源碼,創(chuàng)建了一個(gè) AnonymousObservableSink 通道對(duì)象,并持有 observer(觀察者)、cancel(銷毀者),同時(shí)調(diào)用了 AnonymousObservableSink 的函數(shù) run(),即 AnonymousObservableSink.run(A)
    • 進(jìn)入 AnonymousObservableSink類的函數(shù) run() 源碼, AsubscribeHandler 閉包回調(diào),并傳入一個(gè) AnyObserver 對(duì)象,即 A.subscribeHandler(sink)
    • 進(jìn)入 AnonymousObservableSink 的函數(shù) on() 的實(shí)現(xiàn),這里將 event 分解成了不同的事件,并調(diào)用 AnonymousObservableSink 的函數(shù) forwardOn(),即 AnonymousObservableSink.on() --> AnonymousObservableSink.forwardOn()
    • 進(jìn)入 AnonymousObservableSink 的函數(shù) forwardOn()實(shí)現(xiàn),其具體實(shí)現(xiàn)在父類 Sink 中,調(diào)用了 AnonymousObserver 的函數(shù) on(),即 AnonymousObservableSink.forwardOn() --> AnonymousObserver.on()
    • 進(jìn)入AnonymousObserver 的函數(shù) on(),其具體實(shí)現(xiàn)在父類 ObserverBase 中,調(diào)用了 AnonymousObserver 的函數(shù) onCore(),即 AnonymousObserver.on() --> AnonymousObserver.onCore()
    • 進(jìn)入 AnonymousObserver 的函數(shù) onCore() 的實(shí)現(xiàn),BeventHandler 閉包回調(diào),即 B.eventHandler(event)
  • 發(fā)送信號(hào) onNext()

    • 會(huì)走到創(chuàng)建 B 的回調(diào)閉包中發(fā)送信號(hào)
    • 然后接著走函數(shù) subscribe() 訂閱信號(hào)的流程

繼承鏈

  • AnonymousObservable 繼承鏈:`AnonymousObservable ---> Producer 生產(chǎn)者 --> Observable --> 遵循 ObservableType 協(xié)議 --> 遵循 ObservableConvertibleType 協(xié)議


    AnonymousObservable 繼承鏈.png
  • AnonymousObserver 繼承鏈:AnonymousObservable --> ObserverBase --> 遵循 Disposable、ObserverType 協(xié)議

    AnonymousObserver 繼承鏈.png

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,488評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,034評(píng)論 3 414
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 175,327評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,554評(píng)論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,337評(píng)論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,883評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,975評(píng)論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,114評(píng)論 0 286
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,625評(píng)論 1 332
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,555評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,737評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,244評(píng)論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 43,973評(píng)論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,615評(píng)論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,343評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,699評(píng)論 2 370

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

  • 前言:這幾篇關(guān)于RxSwift源碼分析的文章主要是對(duì)源碼進(jìn)行解析,不涉及到RxSwift的具體使用。具體使用可以查...
    盾子閱讀 706評(píng)論 1 5
  • RxSwift的核心邏輯很重要,是分析整個(gè)框架的基礎(chǔ)。希望通俗易通,沒有弄思維導(dǎo)圖,個(gè)人覺得太多對(duì)象和線條的思維導(dǎo)...
    無悔zero閱讀 741評(píng)論 1 3
  • 前言 通過上一篇內(nèi)容RxSwift學(xué)習(xí)--核心邏輯初探,對(duì)RxSwift有了些初步的認(rèn)知,下面通過源碼來看一下Rx...
    Henry_Jeannie閱讀 398評(píng)論 0 3
  • 透視RxSwift核心邏輯 篇幅稍微有點(diǎn)長,了解程度不同,可以跳過某些部分。如果對(duì)源碼比較熟悉的,建議直接看圖就行...
    silasjs閱讀 1,377評(píng)論 2 21
  • 注:代碼塊中的...是一些不需要顯示的代碼,直接用...替代了,rx的思維導(dǎo)圖我后面重新畫了一張,老漂亮了,畫出經(jīng)...
    越來越胖了閱讀 520評(píng)論 0 3