RxSwift核心逻辑

RxSwift的使用三步曲

第一步:创建序列

let ob = Observable<Any>.create { observer  in
    return Disposables.create()
}

第二步:订阅序列

ob.subscribe(onNext: { text in
    print("订阅信息: \(text)")
}, onError: { error in
    print("error: \(error)")
}, onCompleted: {
    print("订阅结束")
}) {
    print("已销毁")
}

第三步:发送信号

let ob = Observable<Any>.create { observer  in
    obserber.onNext("你好明天")
    return Disposables.create()
}

整体代码

let ob = Observable<Any>.create { observer  in
    obserber.onNext("你好明天")
    return Disposables.create()
}
ob.subscribe(onNext: { text in
    print("订阅信息: \(text)")
}, onError: { error in
    print("error: \(error)")
}, onCompleted: {
    print("订阅结束")
}) {
    print("已销毁")
}
.disposed(by: disposeBag)

分析代码

  • 1:创建序列后,RxSwift返回了一个observer,在这个闭包内返回了Disposables.create(),创建的序列。
  • 2:订阅序列的各个信息,发送成功,结束等等的信号
  • 3:发送的信号由RxSwift返回的observer来发送,这样形成一个完整的环。
    那么这个observer怎么来的?在onNext中发送的“你好明天”是怎么到订阅的text中的呢?以及,这些信号怎么发送给订阅者的呢?
  • 4:猜想:以UIButton为例子,UI序列的相应,比如UIButton它的点击事件,监听的就是点击事件,这个事件由UIButton来发送,而UIButton的事件响应,是依赖于target,在对应的target去实现响应的event。
    那么在RxSwift中,UIControl为什么能够监听到UI层,猜测是UIControl.addTarget(rx内部类),事件的响应就由rx内部类来响应,类似于中间类或者是proxy。
    同理,self.button.rx.tap.subscribe(),这个点击事件就是通过UIControl响应层去添加响应,而且这个响应不再是原始的UI事件的响应了,也不在控制器中了,在rx的内部类中,所以在事件中可以直接调用observer的onNext方法,来发送响应的信号。

还有一个在onNext中发送的“你好明天”是怎么到订阅的text中的呢?这个问题我们没有找到答案,继续去查看RxSwift的源码。

RxSwift源码分析

前提因素:首先,通过creat来创建了一个序列,所以应该先去探索creat这个方法,而能订阅到“你好明天”这段字符串,依赖于发送信号obserber.onNext("你好明天"),而代码顺序是从上往下执行的,那在ob.subscribe中能打印onNext发送的“你好明天”,那说明在ob.subscribe中应该暗藏一句代码,执行onNext。即subscribe的闭包执行依赖发送信号onNext的执行。带着这些前提,去分析查看源码。

一 首先来看一下creat序列的创建

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

creat创建了一个匿名序列AnonymousObservable

final private class AnonymousObservable<Element>: Producer<Element> {
    typealias SubscribeHandler = (AnyObserver<Element>) -> Disposable

    let subscribeHandler: SubscribeHandler

    init(_ subscribeHandler: @escaping SubscribeHandler) {
        self.subscribeHandler = subscribeHandler
    }

    override func run<Observer: ObserverType>(_ observer: Observer, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where Observer.Element == Element {
        let sink = AnonymousObservableSink(observer: observer, cancel: cancel)
        let subscription = sink.run(self)
        return (sink: sink, subscription: subscription)
    }
}

这个匿名序列继承自Producer,而且init方法保存了通过create传递的self.subscribeHandler。
Producer继承自Observable即序列的基类,Observable遵循了协议ObservableType,ObservableType协议提供了subscribe方法。该协议是贯穿全剧的,可扩展协议可以根据不同的内容需求扩展。
匿名序列的run方法,就是重写的父类的方法。


create方法比较重要的内容

二 subscribe订阅信号的内容

 public func subscribe(_ on: @escaping (Event<Element>) -> Void) -> Disposable {
        let observer = AnonymousObserver { e in
            on(e)
        }
        return self.asObservable().subscribe(observer)
    }

在订阅的时候,创建了一个匿名内部类AnonymousObserver ,AnonymousObserver继承自继承ObserverBase,ObserverBase遵循了协议Disposable, ObserverType,而AnonymousObserver在初始化的时候保存了eventHandler。self.asObservable().subscribe(observer),.asObservable这个是可观察序列基类Observerble的方法,是采用的接口隔离原则。事实上万物皆可序列,而比如以UISwitch为例:

UISwitch().rx.value.asObservable()
            .subscribe { bool in
                
            }
            .disposed(by: disposeBag)

为什么需要调用asObservable呢?

    public var value: ControlProperty<Bool> {
        return base.rx.controlPropertyWithDefaultEvents(
            getter: { uiSwitch in
                uiSwitch.isOn
            }, setter: { uiSwitch, value in
                uiSwitch.isOn = value
            }
        )
    }

从源码中看到,value是ControlProperty类型,ControlProperty遵循了协议ControlPropertyType,不是可观察序列,通过调用asObservable强转为可观察序列,然后利用可观察序列的各种方法,来达到相应的需求,这也是万物皆可序列的第二种解释。

而asObservable返回的就是一个可观察序列,返回的是self.values,类型就是 Observable<PropertyType>

 let values: Observable<PropertyType>
 public func asObservable() -> Observable<Element> {
        self.values
    }

继续探究self.asObservable().subscribe(observer),subscribe的内容。subscribe执行了父类Produver实现的协议方法subscribe,然后执行了self.run方法,即执行了匿名序列AnonymousObservable的run方法

 override func run<Observer: ObserverType>(_ observer: Observer, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where Observer.Element == Element {
        let sink = AnonymousObservableSink(observer: observer, cancel: cancel)
        let subscription = sink.run(self)
        return (sink: sink, subscription: subscription)
    }

匿名序列AnonymousObservable的run方法,执行了AnonymousObservableSink的run方法

 func run(_ parent: Parent) -> Disposable {
        parent.subscribeHandler(AnyObserver(self))
    }

AnonymousObservable 调用把AnonymousObservableSink作为参数,调用创建的闭包,执行了保存的subscribeHandler即是在create的时候保存的闭包,并将AnyObserver(self)传递了进去,这就是在create的闭包中传来的observer。流程如下图所示:


subscribe流程

三 onNext发送信号

extension ObserverType {
    
    /// Convenience method equivalent to `on(.next(element: Element))`
    ///
    /// - parameter element: Next element to send to observer(s)
    public func onNext(_ element: Element) {
        self.on(.next(element))
    }
}

执行了匿名类AnonymousObserver的父类ObserverBase的on方法

 func on(_ event: Event<Element>) {
        switch event {
        case .next:
            if load(self.isStopped) == 0 {
                self.onCore(event)
            }
        case .error, .completed:
            if fetchOr(self.isStopped, 1) == 0 {
                self.onCore(event)
            }
        }
    }

然后执行了匿名类AnonymousObserver的onCore方法

override func onCore(_ event: Event<Element>) {
        self.eventHandler(event)
    }

然后在这个方法中执行了匿名类在subscribe中保存的eventHandler,完整的流程图如下:


三步曲

总结:Observable的核心流程
从create开始,得到一个匿名观察序列AnonymousObservable,这个匿名类保存了subscribeHandler。
然后通过订阅方法subscribe创建了匿名observer保存了事件eventHandler,并且通过AnonymousObservable的run方法将observer传递,最终执行subscribeHandler将信号传递。
发送信号onNext最终通过核心方法onCore执行了eventHandler将事件传递。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352

推荐阅读更多精彩内容