RxSwift(2)—— 核心邏輯源碼分析

就問此時此刻還有誰伐割?45度仰望天空妥箕,該死连躏!我這無處安放的魅力萨惑!


RxSwift目錄直通車--- 和諧學習捐康,不急不躁!


作為ReactiveX家族之一的RxSwiftGithub截止現在Star:16K.為什么這個框架如此受歡迎庸蔼,作為函數響應式框架典型代表吹由,底層實現又是如何實現的呢?這一篇文章全面解密

RxSwift核心流程

RxSwift這個優(yōu)秀的框架朱嘴,設計的api也是非常精簡倾鲫,讓陌生的用戶也能非常快速上手

  • 1: 創(chuàng)建序列
  • 2: 訂閱序列
  • 3:發(fā)送信號
// 1: 創(chuàng)建序列
_ = Observable<String>.create { (obserber) -> Disposable in
    // 3:發(fā)送信號
    obserber.onNext("Cooci -  框架班級")
    return Disposables.create()  // 這個銷毀不影響我們這次的解讀
    // 2: 訂閱序列
    }.subscribe(onNext: { (text) in
        print("訂閱到:\(text)")
    })

// 控制臺打悠兼摇:“訂閱到:Cooci -  框架班級”

我剛開始在探索的時候乌昔,我是比較好奇的:為什么我們的Cooci - 框架班級這個字符串會在訂閱序列的subscribe的閉包打印。下面是我的代碼分析

分析代碼:

  • 1:創(chuàng)建序列的代碼 Create 后面的 閉包A 里面有 3:發(fā)送信號壤追,如果要執(zhí)行 發(fā)送信號 磕道,必然要來到這個閉包A
  • 2:我們執(zhí)行 2: 訂閱序列 創(chuàng)建了 閉包B
  • 3:通過結果我們顯然知道,先執(zhí)行 閉包ACooci - 框架班級 傳給了 閉包B
  • 猜測:代碼里面嵌套了閉包的執(zhí)行調用行冰!猜測的真實性溺蕉,我們開始解讀源碼來驗證

PS: 說實話 RxSwift框架的源碼的確比較復雜并且很多伶丐,很多基礎薄弱或者耐性不夠的小伙伴很容易放棄。但是你看到這篇博客疯特,你有福了:我會快速簡短給你介紹哗魂,在最后面會附上我繪制的思維導圖!

RxSwift核心邏輯

創(chuàng)建序列

extension ObservableType {
    // MARK: create
    public static func create(_ subscribe: @escaping (AnyObserver<E>) -> Disposable) -> Observable<E> {
        return AnonymousObservable(subscribe)
    }
}

大家可以很清晰看到我們的 可觀察序列 的創(chuàng)建是利用協(xié)議拓展功能的create方法實現的漓雅,里面創(chuàng)建了一個 AnonymousObservable(匿名可觀察序列) 命名還是體現了作者的思維 :這個類就是一個內部類录别,具備一些通用特性(具有自己功能的類才會命名) 下面我貼出這個類的繼承關系

從上面的圖,我們可以清晰的看到的繼承關系邻吞。那么這么多的內容還有那么多層嵌套组题,這個地方我們需要掌握什么:

  • create 方法的時候創(chuàng)建了一個內部對象 AnonymousObservable
  • AnonymousObservable 保存了外界的閉包
  • AnonymousObservable繼承了 Producer 具有非常重要的方法 subscribe

訂閱序列

這里說明這個訂閱方法 subscribe 和我們上面所說的 subscribe 不是同一個方法

來自于對 ObservableType 的拓展功能

extension ObservableType {
    public func subscribe(onNext: ((E) -> Void)? = nil, ...) -> Disposable {
           // 因為篇幅 省略不影響我們探索的代碼
            let observer = AnonymousObserver<E> { event in                
                switch event {
                case .next(let value):
                    onNext?(value)
                case .error(let error):
                    if let onError = onError {
                        onError(error)
                    }
                    else {
                        Hooks.defaultErrorHandler(callStack, error)
                    }
                    disposable.dispose()
                case .completed:
                    onCompleted?()
                    disposable.dispose()
                }
            }
            return Disposables.create(
                self.asObservable().subscribe(observer),
                disposable
            )
    }
}

代碼說明:

  • E 這里的意思是 Swift 的關聯類型,這個如果仔細看過可觀察序列的繼承鏈源碼應該不難得出:這個E 就是我們的 序列類型抱冷,我們這里就是String
public class Observable<Element> : ObservableType {
    /// Type of elements in sequence.
    public typealias E = Element
  • 創(chuàng)建了一個 AnonymousObserver (匿名內部觀察者) 手法和我們的 AnonymousObservable 差不多崔列,它這里的初始化是閉包參數,保存了外界的 onNext, onError , onCompleted , onDisposed 的處理回調閉包的調用,下面我還是給大家貼出 觀察者 的繼承鏈關系旺遮,幫助大家理解
  • self.asObservable() 這個是我們的 RxSwift 為了保持一致性的寫法
  • self.asObservable().subscribe(observer)其實本質就是 self.subscribe(observer),通過可觀察序列的繼承關系峻呕,我們可以非常快速的定位 Producer 訂閱代碼
override func subscribe(_ observer: O) -> Disposable where O.E == Element {
        if !CurrentThreadScheduler.isScheduleRequired {
            // 篇幅原因趣效,我們省略一些代碼,方便我們理解
            ...
            return disposer
        }
        else {
            return CurrentThreadScheduler.instance.schedule(()) { _ in
                let disposer = SinkDisposer()
                let sinkAndSubscription = self.run(observer, cancel: disposer)
              // 篇幅原因猪贪,我們省略一些代碼跷敬,方便我們理解
              ...
                return disposer
            }
        }
    }
  • 關于銷毀代碼和調度者代碼這里不分析
  • self.run 這個代碼最終由我們生產者 Producer 延伸到我們具體的事務代碼 AnonymousObservable.run
override func run (...) {
    let sink = AnonymousObservableSink(observer: observer, cancel: cancel)
    let subscription = sink.run(self)
    return (sink: sink, subscription: subscription)
}
  • sink.run的寫法也是比較好的,業(yè)務處理的還是下沉了热押,讓分工更加明確
func run(_ parent: Parent) -> Disposable {
    return parent._subscribeHandler(AnyObserver(self))
}
  • parent 就是上面?zhèn)鬟^來的AnonymousObservable對象
  • 我們非常興奮的看到 AnonymousObservable._subscribeHandler,從這句代碼我們解惑了為什么我們的序列訂閱的時候流程會執(zhí)行我們 序列閉包西傀,然后去執(zhí)行 發(fā)送響應
  • 發(fā)送響應的代碼等會分析,這里還有一個比較重要的家伙 AnyObserver(self)
public init<O : ObserverType>(_ observer: O) where O.E == Element {
    self.observer = observer.on
}
  • 在這個構造方法里面桶癣,我們創(chuàng)建了一個結構體 AnyObserver 保存了一個信息 AnonymousObservableSink .on 函數拥褂,不是 AnonymousObservableSink,這個地方一般初次來到這里的人都會犯錯誤。不知道你是否意識到了牙寞!

發(fā)送響應

我們從上面的分析饺鹃,非常清晰:
obserber.onNext("Cooci - 框架班級") 的本質是: AnyObserver.onNext("Cooci - 框架班級")

這時候發(fā)現我們的AnyObserver 是沒有這個方法,這很正常间雀!一般思路悔详,找父類,找協(xié)議

extension ObserverType {
    public func onNext(_ element: E) {
        self.on(.next(element))
    }
}
  • 外界 obserber.onNext("Cooci - 框架班級") 再次變形 :AnyObserver.on(.next("Cooci - 框架班級")) ,這里大家一定要主要惹挟,這個AnyObserver調用了 on 里面?zhèn)鞯氖?.next函數, .next函數帶有我們最終的參數
public struct AnyObserver<Element> : ObserverType {
    public init<O : ObserverType>(_ observer: O) where O.E == Element {
        self.observer = observer.on
    }
    public func on(_ event: Event<Element>) {
        return self.observer(event)
    }
}
  • self.observer 構造初始化就是:AnonymousObservableSink .on 函數
  • 看到這里又要變形咯:self.observer(event) -> AnonymousObservableSink .on(event) 其中 event = .next("Cooci - 框架班級") 最終我們的核心邏輯又回到了 sink 這個神奇的管子茄螃,看到這里不禁拍案叫絕, RxSwift這個設計能力连锯,還有誰~~~
class AnonymousObservableSink<O: ObserverType>: Sink<O>, ObserverType {
    func on(_ event: Event<E>) {
        switch event {
        case .next:
            if load(self._isStopped) == 1 {
                return
            }
            self.forwardOn(event)
        case .error, .completed:
            if fetchOr(self._isStopped, 1) == 0 {
                self.forwardOn(event)
                self.dispose()
            }
        }
    }
}
```Swift
* `self.forwardOn(event)` 這也是執(zhí)行的核心代碼归苍,因為 `AnonymousObservableSink` 繼承 `Sink`  這里還有封裝用狱,請看下面的代碼

class Sink<O : ObserverType> : Disposable {
final func forwardOn(_ event: Event<O.E>) {
if isFlagSet(self._disposed, 1) {
return
}
self._observer.on(event)
}
}

* 其中 `self._observer` 就是我們初始化保存的 `觀察者:AnonymousObserver`
* 那么我們變形得出本質就是:`AnonymousObserver.on(.next("Cooci -  框架班級"))`,我的天啊! 這里邏輯輾轉回到了我們 `訂閱序列` 時候創(chuàng)建的 `AnonymousObserver` 的參數閉包的調用!所有的一切感覺是這樣的啰嗦拼弃,但又是這么的順其資源夏伊。

```Swift
let observer = AnonymousObserver<E> { event in
    switch event {
    case .next(let value):
        onNext?(value)
    case .error(let error):
        if let onError = onError {
            onError(error)
        }
        else {
            Hooks.defaultErrorHandler(callStack, error)
        }
        disposable.dispose()
    case .completed:
        onCompleted?()
        disposable.dispose()
    }
}
  • 判斷 event 進而調用 onNext?(value) ,因為枚舉的關聯值(Swift很強大的功能)value = "Cooci - 框架班級", 接下來就是外界 onNext閉包的調用傳參,那么這個時候源碼解析到這里肴敛,我相信你已經完全掌握了RxSwift的核心邏輯署海,最后這里附上我們的分析圖解

總結:RxSwift的結構

  • 1:就是序列感念 滿世界都是序列 - 編碼統(tǒng)一 ,隨時隨地享用
  • 2:通過函數式思想吧一些列的需求操作下沉(把開發(fā)者不關心的東西封裝) - 優(yōu)化代碼医男,節(jié)省邏輯
  • 3:RxSwift最典型的特色就是解決Swift這門靜態(tài)語言的響應能力砸狞,利用隨時間維度序列變化為軸線,用戶訂閱關心能隨軸線一直倍扑螅活刀森,達到訂閱一次,響應一直持續(xù)~

就問此時此刻還有誰报账?45度仰望天空研底,該死!我這無處安放的魅力透罢!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末榜晦,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子羽圃,更是在濱河造成了極大的恐慌乾胶,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件朽寞,死亡現場離奇詭異识窿,居然都是意外死亡,警方通過查閱死者的電腦和手機脑融,發(fā)現死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門喻频,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人肘迎,你說我怎么就攤上這事甥温。” “怎么了妓布?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵窿侈,是天一觀的道長。 經常有香客問我秋茫,道長史简,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮圆兵,結果婚禮上跺讯,老公的妹妹穿的比我還像新娘。我一直安慰自己殉农,他們只是感情好刀脏,可當我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著超凳,像睡著了一般愈污。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上轮傍,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天暂雹,我揣著相機與錄音,去河邊找鬼创夜。 笑死杭跪,一個胖子當著我的面吹牛,可吹牛的內容都是我干的驰吓。 我是一名探鬼主播涧尿,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼檬贰!你這毒婦竟也來了姑廉?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤翁涤,失蹤者是張志新(化名)和其女友劉穎桥言,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體迷雪,經...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年虫蝶,在試婚紗的時候發(fā)現自己被綠了章咧。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡能真,死狀恐怖赁严,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情粉铐,我是刑警寧澤疼约,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站蝙泼,受9級特大地震影響程剥,放射性物質發(fā)生泄漏。R本人自食惡果不足惜汤踏,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一织鲸、第九天 我趴在偏房一處隱蔽的房頂上張望舔腾。 院中可真熱鬧,春花似錦搂擦、人聲如沸稳诚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽扳还。三九已至,卻和暖如春橱夭,著一層夾襖步出監(jiān)牢的瞬間氨距,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工徘钥, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留衔蹲,地道東北人。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓呈础,卻偏偏與公主長得像舆驶,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子而钞,可洞房花燭夜當晚...
    茶點故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內容