RxSwift核心原理探究

在之前有淺淺的分享了一下RxSwift簡單使用空执,
但是同樣的也有一些困惑伴隨著我,比如它是如何實現(xiàn)穗椅,為什么所有的對象類都可以使用rx方法呢辨绊,再比如Timer實現(xiàn)方式為什么跟原生的又差別如此之大呢,帶著這些個疑問匹表,就想著看一下這強大的庫是如何實現(xiàn)的门坷,下面大概分享一下個人的拙見;

RxSwift本質(zhì)上就是信號的產(chǎn)生袍镀、訂閱默蚌、發(fā)送跟銷毀,核心邏輯就是產(chǎn)生苇羡、訂閱绸吸、發(fā)送三步曲:1、創(chuàng)建信號 2设江、訂閱信號 3锦茁、發(fā)送信號,下面就以一個最簡單信號創(chuàng)建訂閱流程來分析一下叉存,它內(nèi)部是怎么實現(xiàn)的码俩;

先創(chuàng)建Observable可觀察者對象,然后使用subscribe訂閱鹉胖,最后第三步發(fā)送信號就是隱藏步驟握玛,實際開發(fā)中,我們不需要去直接調(diào)用onNext甫菠、onError操作;

class ViewController: UIViewController {
    let disposeBag = DisposeBag()
    
    override func viewDidLoad() {
        super.viewDidLoad() 
        // 1冕屯、創(chuàng)建信號
        let ob = Observable<Any>.create { observer in
            // 3寂诱、發(fā)送信號
            observer.onNext("下一步")
//            observer.onError(NSError.init(domain: "Chris's error", code: 10086, userInfo: nil))
            observer.onCompleted()
            
            return Disposables.create()
        }
        
        // 2、訂閱信號
        let _ = ob.subscribe { text in
            print("訂閱到了:\(text)")
        } onError: { error in
            print("error:\(error)")
        } onCompleted: {
            print("完成")
        } onDisposed: {
            print("銷毀")
        }
        .disposed(by: disposeBag) 
    }
}

一安聘、創(chuàng)建信號

1痰洒、Observable<Any>.create

通過Observable<Any>.create創(chuàng)建一個可觀察對象瓢棒,傳入一個尾隨閉包作為參數(shù),點進去create看一下其內(nèi)部實現(xiàn)丘喻,發(fā)現(xiàn)create是ObservableType的一個擴展方法;


image.png

而ObservableType其實是一個協(xié)議脯宿,繼承自O(shè)bservableConvertibleType,Observable遵循了ObservableType協(xié)議泉粉,即Observable調(diào)用ObservableType協(xié)議里的create方法连霉;


image.png

2、AnonymousObservable.subscribeHandler

create方法內(nèi)部就一句代碼 AnonymousObservable(subscribe)嗡靡,AnonymousObservable這個字面意思跺撼,是個匿名的可觀察者,把subscribe傳給AnonymousObservable讨彼,這個subscribe是我們創(chuàng)建的尾隨閉包歉井,那么AnonymousObservable里面又做什么處理呢?只能繼續(xù)往下翻了哈误;

public static func create(_ subscribe: @escaping (AnyObserver<Element>) -> Disposable) -> Observable<Element> {
        AnonymousObservable(subscribe)
    }

點進去AnonymousObservable看哩至,發(fā)現(xiàn)AnonymousObservable給回調(diào)閉包取了個別名,又定義了一個全局變量subscribeHandler蜜自,保存我們外面?zhèn)鬟M來的閉包菩貌;


image.png

這里我們看到AnonymousObservable是繼承的Producer,而Producer點擊發(fā)現(xiàn)袁辈,它其實是繼承自O(shè)bservable菜谣;


image.png

到這一步,其實我們創(chuàng)建訂閱信號的步驟就已經(jīng)完成了晚缩;可能有點繞尾膊,總結(jié)一下,本質(zhì)的思想就是通過父類Observable創(chuàng)建的訂閱信號閉包荞彼,交給子類AnonymousObservable去保存實現(xiàn)冈敛;

二、訂閱信號

1鸣皂、創(chuàng)建一個AnonymousObserver訂閱者

上面我們已經(jīng)說了抓谴,我們創(chuàng)建的ob對象,其實是AnonymousObserver對象寞缝,所以此處subscribe就是創(chuàng)建一個AnonymousObserver訂閱者癌压;


image.png

2、AnonymousObserver初始化的時候保存eventHandler

前面的disposable這些銷毀對象的創(chuàng)建先不看荆陆,重點看return返回值滩届,self.asObservable().subscribe(observer) 這個做為參數(shù)傳給可銷毀對象Disposables;
observer這個其實就是訂閱者被啼,它是AnonymousObserver對象帜消,繼承自O(shè)bserverBase棠枉,后面?zhèn)魅氲膮?shù)是個事件回調(diào)閉包,AnonymousObserver就是將eventHandler事件保存下來泡挺;注意到里面還有個onCore方法辈讶,里面是調(diào)用eventHandler執(zhí)行操作;


image.png

AnonymousObserver的父類ObserverBase娄猫,它里面有個on方法贱除,里面就一個switch方法,Event是個枚舉類稚新,往下看就能看到我們熟悉next\error\completed勘伺,再往后就是調(diào)用onCore方法,這個調(diào)用的時機后面具體分析褂删;


image.png
image.png

3飞醉、self.asObservable().subscribe(observer) 方法調(diào)用

接下來看,self上面也說了屯阀,是AnonymousObservable對象缅帘,asObservable也不用過多關(guān)心,其實就是類似OC里面的多態(tài)难衰,強制性返回Observable Class钦无,重點看subscribe方法調(diào)用,傳入的observer參數(shù)盖袭,上面步驟2已經(jīng)說過了失暂;

image.png

4、producer.subscribe

subscribe方法點擊jump發(fā)現(xiàn)好多地方都有該方法鳄虱,如上文所說弟塞,ob本質(zhì)是AnonymousObservable對象,他們的繼承鏈關(guān)系A(chǔ)nonymousObservable->Producer->Observable拙已;Observable又遵循ObservableType協(xié)議决记,上訴幾個類都有實現(xiàn)subscribe方法,具體也不知道要執(zhí)行哪一個方法倍踪,所以這個時候找起來就比較麻煩了系宫,我這個比較懶,不想挨個去找了建车,此時最簡單的方法其實就是查看調(diào)用堆棧了扩借;


image.png

這里可以發(fā)現(xiàn)asObservable().subscribe是執(zhí)行的父類Producer里面的subscribe方法,其實仔細查看源碼也會發(fā)現(xiàn)缤至,AnonymousObservable沒有實現(xiàn)subscribe方法往枷,而Observable里面只是調(diào)用rxAbstractMethod()構(gòu)造方法而已,做一些錯誤處理凄杯,也沒有具體實現(xiàn)错洁,所以關(guān)鍵代碼還是在Producer里;
分析Producer里面的方法戒突,主要就是通過不同條件屯碴,執(zhí)行不同代碼,其實本質(zhì)執(zhí)行的都是執(zhí)行下面三行代碼膊存;

    let disposer = SinkDisposer()
    let sinkAndSubscription = self.run(observer, cancel: disposer)
    disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink, subscription: sinkAndSubscription.subscription)

這個schedule就先不深究了导而,調(diào)用之后還是會執(zhí)行action方法,就是剛才subscribe里面的閉包函數(shù)隔崎;


image.png

5今艺、AnonymousObservable.run

重點還是看一下上面run方法;調(diào)用的AnonymousObservable對象本身的run方法爵卒,run里面又調(diào)用AnonymousObservableSink的run方法虚缎,這個AnonymousObservableSink又是啥子?xùn)|西?钓株?实牡?只能接著往下看了


image.png

6、AnonymousObservableSink.run

AnonymousObservableSink是繼承自Sink轴合,Sink是什么先不深究创坞,里面定義了一些方法實現(xiàn),里面保存了observe受葛、cancel對象题涨;


image.png

7、parent.subscribeHandler(AnyObserver(self))

看當(dāng)前的這個run方法总滩,里面就一句代碼纲堵,parent就是步驟5傳入的self,即AnonymousObservable對象咳秉,即表示AnonymousObservable調(diào)用subscribeHandler方法婉支;


image.png

這個時候就串起來了,前文創(chuàng)建信號的時候講過創(chuàng)建Observable的訂閱信號的時候澜建,交給子類AnonymousObservable去保存向挖,這個時候就是調(diào)用之前保存的閉包回調(diào)了,就會來到下面這一步炕舵;

image.png

三何之、發(fā)送信號

1、 AnonymousObserver.onNext執(zhí)行

根據(jù)上面的一系列操作咽筋,我們已經(jīng)可以執(zhí)行create里面的回調(diào)了昧诱,這一步我們開頭的時候也說了,實際開發(fā)中不需要我們手動去調(diào)用onNext卖擅、onError等方法,但是既然我們是探究他的原理虱痕,那就繼續(xù)往下看;

這個observer是個什么東西辐赞?為什么能調(diào)用onNext等方法呢部翘?

上面步驟7有提到,subscribeHandler.(AnyObserver(self))响委,我們可以得出observer == AnyObserver(self)新思,那我們點開AnyObserver,發(fā)現(xiàn)它其實就是個結(jié)構(gòu)體赘风,遵循了ObserverType協(xié)議夹囚,用observer保存了AnonymousObservableSink的on方法,AnonymousObservableSink我們在訂閱信號的步驟6有提到邀窃,截圖中有被收納起來的on方法荸哟;

所以create中的observer =AnyObserver(self),里面AnyObserver所持有的對象self.observer = AnonymousObservableSink.on蛔翅;


image.png

2敲茄、ObserverType.onNext

到了這一步,我們還是不知道onNext怎么來的山析,既然它自身沒有實現(xiàn)堰燎,那么只能去看他的協(xié)議方法了,果不其然笋轨,在協(xié)議擴展方法里面實現(xiàn)了onNext秆剪,往下看,其實他是調(diào)用當(dāng)前的on方法爵政,傳入.next枚舉外帶value值仅讽;

image.png

3、AnonymousObservableSink.on

繼續(xù)走會發(fā)現(xiàn)钾挟,調(diào)用了AnyObserver本身的on方法洁灵,實現(xiàn)就一行代碼;

self.observer(event)

上面已經(jīng)分析出了observer == AnonymousObservableSink.on掺出,其實這里就是調(diào)用AnonymousObservableSink的on方法徽千,繼續(xù)往下看看sink.on里面做了什么操作;


image.png

下面是AnonymousObservableSink的on方法汤锨,這個方法很眼熟双抽,跟前文中提到的ObserverBase的on方法很類似,只是ObserverBase的on最后是調(diào)用的onCore方法闲礼,這邊調(diào)用的是forwardOn牍汹;


image.png

4铐维、Sink.forwardOn

forwardOn當(dāng)前類沒有實現(xiàn),只能去它的父類找慎菲,繼續(xù)網(wǎng)上找嫁蛇,發(fā)現(xiàn)它是調(diào)用的self.observer.on方法,這個self.observer之前訂閱信號的步驟6有提到過钧嘶,sink保存observer跟cancel對象用來后續(xù)處理棠众,唉,這邊就用到了有决;


image.png

5、ObserverBase.on

這個self.observer打印發(fā)現(xiàn)它其實是AnonymousObserver類空盼,繼承至ObserverBase书幕,所以到這一步,還是調(diào)用我們前文提到的ObserverBase的on方法揽趾,在往下執(zhí)行onCore台汇;


image.png

6、AnonymousObserver.onCore->self.eventHandler()

上一步驟的self其實是AnonymousObserver篱瞎,那么onCore往下執(zhí)行就到了我們訂閱信號的步驟2提到的苟呐,執(zhí)行AnonymousObserver保存下來eventHandler事件;


image.png

這個eventHandler事件俐筋,在訂閱信號創(chuàng)建的時候牵素,被我隱藏了,沒有展開講澄者,這邊展開來看一下笆呆,里面到底有什么秘密;

7粱挡、onNext赠幕、onError、onCompleted询筏、dispose執(zhí)行

image.png

點進去發(fā)現(xiàn)這個閉包就是響應(yīng)event事件榕堰,對不同事件執(zhí)行不同方法,onNext就是我們subscribe傳入的閉包回調(diào)嫌套,value就是我們onNext傳入的值逆屡;

    public func onNext(_ element: Element) {
        self.on(.next(element))
    }
image.png

到這里我們整個創(chuàng)建、訂閱灌危、發(fā)送信號整個過程就已經(jīng)分析完了康二,前前后后執(zhí)行了二十多個方法;里面的涉及了很多的繼承勇蝙、擴展沫勿、協(xié)議等等挨约,可能有點繞;

四产雹、小結(jié):

總的流程有點繞诫惭,下面簡單梳理一下:
首先是帶able結(jié)尾的信號生產(chǎn)者繼承鏈關(guān)系:


信號生產(chǎn)者繼承鏈

然后是帶observer結(jié)尾的信號訂閱者繼承鏈關(guān)系:


信號訂閱者繼承鏈

整體核心流程如下:


image.png

從圖中也可以看出,Observable蔓挖、Observer分工明確夕土,sink是起到承上啟下的作用,同時保存了observer瘟判、cancel怨绣,訂閱信號的run方法,發(fā)送信號的on方法拷获,都是從這邊調(diào)用的篮撑,這個類就相當(dāng)于一個業(yè)務(wù)中間層,所有業(yè)務(wù)邏輯都在這里處理匆瓜,通過這個中間件可以串聯(lián)Observable信號生產(chǎn)者跟Observer信號訂閱者赢笨;

RxSwift使用了大量的繼承、協(xié)議驮吱、擴展茧妒,實現(xiàn)了接口分離,模塊分工清晰左冬,里面設(shè)計雖然很復(fù)雜桐筏,但是暴露API都是很簡單的,讓開發(fā)者只想關(guān)心當(dāng)前業(yè)務(wù)的開發(fā)又碌,無需關(guān)心業(yè)務(wù)直接的調(diào)度九昧,這種設(shè)計模式可以很好的實現(xiàn)業(yè)務(wù)分離。
我最近做的音視頻開發(fā)的模塊毕匀,視頻的渲染跟解碼就是通過這種方式使之分離铸鹰,誰要渲染直接訂閱當(dāng)前暴露的接口就可以,調(diào)度者就根據(jù)訂閱的信號去返回AVframe就可以皂岔,也無需關(guān)心是誰訂閱的蹋笼,同樣的,音頻幀處理也是這樣躁垛。其實我們平時開發(fā)中也可以借鑒這種設(shè)計模式剖毯,分析框架最主要的就是學(xué)習(xí)其優(yōu)秀的設(shè)計模式,為我所用教馆;

以上逊谋,就是個人理解的RxSwift大體實現(xiàn)流程,如有不對土铺,歡迎指正=鹤獭0鬻蕖!

CSDN地址:https://blog.csdn.net/weixin_37498529/article/details/126560786
知乎地址:https://zhuanlan.zhihu.com/p/560495890

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末究恤,一起剝皮案震驚了整個濱河市俭令,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌部宿,老刑警劉巖抄腔,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異理张,居然都是意外死亡赫蛇,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進店門涯穷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來棍掐,“玉大人,你說我怎么就攤上這事拷况。” “怎么了掘殴?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵赚瘦,是天一觀的道長。 經(jīng)常有香客問我奏寨,道長起意,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任病瞳,我火速辦了婚禮揽咕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘套菜。我一直安慰自己亲善,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布逗柴。 她就那樣靜靜地躺著蛹头,像睡著了一般。 火紅的嫁衣襯著肌膚如雪戏溺。 梳的紋絲不亂的頭發(fā)上渣蜗,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天,我揣著相機與錄音旷祸,去河邊找鬼耕拷。 笑死,一個胖子當(dāng)著我的面吹牛托享,可吹牛的內(nèi)容都是我干的骚烧。 我是一名探鬼主播浸赫,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼止潘!你這毒婦竟也來了掺炭?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤凭戴,失蹤者是張志新(化名)和其女友劉穎涧狮,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體么夫,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡者冤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了档痪。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片涉枫。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖腐螟,靈堂內(nèi)的尸體忽然破棺而出愿汰,到底是詐尸還是另有隱情,我是刑警寧澤乐纸,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布衬廷,位于F島的核電站,受9級特大地震影響汽绢,放射性物質(zhì)發(fā)生泄漏吗跋。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一宁昭、第九天 我趴在偏房一處隱蔽的房頂上張望跌宛。 院中可真熱鬧,春花似錦积仗、人聲如沸疆拘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽入问。三九已至,卻和暖如春稀颁,著一層夾襖步出監(jiān)牢的瞬間芬失,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工匾灶, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留棱烂,地道東北人。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓阶女,卻偏偏與公主長得像颊糜,于是被迫代替她去往敵國和親哩治。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,834評論 2 345

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