RxSwift---核心逻辑(二)

在上一章中我们初步的领略了RxSwift的魅力,那么这一章我们就来一起探索RxSwift的核心逻辑

RxSwift的核心流程

RxSwift的使用其实就分为三步,也是我们通常讲的三步曲

  • 1.创建序列
  • 2.订阅序列
  • 3.发送信号
        //1.创建序列
        let ob = Observable<Any>.create { observer in
            //3.发送信号
            observer.onNext("Rx发送信号")
            return Disposables.create()  // 这个销毁不影响我们这次的解读
        }
        
        //2.订阅信号
        ob.subscribe { text in
            print("订阅到了:\(text)")
        } onError: { error in
            print("error:\(error)")
        } onCompleted: {
            print("done")
        } onDisposed: {
            print("销毁")
        }.disposed(by: disposebag)

//打印结果:订阅到了:Rx发送信号

哎~ :为什么我们的订阅到了:Rx发送信号这个字符串会在订阅序列的subscribe的闭包打印,下面是代码分析

代码分析

  • 1:代码的执行顺序是 1 -> 2 -> 3
  • 2:整个代码只有一个输入口 observer.onNext("Rx发送信号")
  • 3:在1中创建了一个闭包A里面有3:发送信号,如果执行发送信号必然要来到闭包A
  • 4:执行2:订阅 创建了闭包B
  • 5:通过打印结果知道:先执行闭包A 然后传给了闭包B

猜测:这样就不能猜出要想把 observer.onNext("Rx发送信号")中的信号在闭包B中打印出来,在subscribe中必然调用了onNext,接下来我们去验证这个猜测是否正确

RxSwift的核心逻辑

创建序列

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

作者通过协议的扩展创建了一个匿名的可观察序列(AnonymousObservable) ,AnonymousObservable是一个内部类,是一个很好设计模式,只返回外部所需要的,至于内部的操作对外部完全匿名,下面我们看下这个类的继承关系

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)
    }
}
    1. create创建了一个匿名对象AnonymousObservable
    1. AnonymousObservable匿名对象保存了外部的闭包
    1. AnonymousObservable继承自Producer, Producer有一个很重要的方法subscribe ------ (函数式编程思想)

订阅序列

我们通过subscribe点进源码

public func subscribe(
        onNext: ((Element) -> Void)? = nil,
        onError: ((Swift.Error) -> Void)? = nil,
        onCompleted: (() -> Void)? = nil,
        onDisposed: (() -> Void)? = nil
    ) -> Disposable {
            let disposable: Disposable
            
            if let disposed = onDisposed {
                disposable = Disposables.create(with: disposed)
            }
            else {
                disposable = Disposables.create()
            }
            
            #if DEBUG
                let synchronizationTracker = SynchronizationTracker()
            #endif
            
            let callStack = Hooks.recordCallStackOnError ? Hooks.customCaptureSubscriptionCallstack() : []
            
            let observer = AnonymousObserver<Element> { event in
                
                #if DEBUG
                    synchronizationTracker.register(synchronizationErrorMessage: .default)
                    defer { synchronizationTracker.unregister() }
                #endif
                
                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
            )
    }
  • 1.subscribe方法中传入了onNext,onError,onCompleted以及onDisposed4个闭包,并且返回Disposable 对象
  • 2.let observer = AnonymousObserver<Element>创建了一个AnonymousObserver匿名的观察者对象,并且把这里传入的闭包给保存起来
  • 3.通过Disposables.create创建了一个销毁者并且返回
  • 4.注意⚠️self.asObservable().subscribe(observer),这里的self.asObservable()其实就是外部的我们通过create方法创建的ob序列,这个是我们的 RxSwift 为了保持一致性的写法,subscribe方法就是创建序列流程中我们看到的Producersubscribe方法,并且把我们创建的AnonymousObserver<Element>对象observer传入了进去
class Producer<Element>: Observable<Element> {
//为了方便我们理解,这里省略了一些不必要的代码 ...
    override func subscribe<Observer: ObserverType>(_ observer: Observer) -> Disposable where Observer.Element == Element {
        if !CurrentThreadScheduler.isScheduleRequired {
        //直接省略...
            return disposer
        }
        else {
            return CurrentThreadScheduler.instance.schedule(()) { _ in
                let disposer = SinkDisposer()
                let sinkAndSubscription = self.run(observer, cancel: disposer)
                disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink, subscription: sinkAndSubscription.subscription)
                return disposer
            }
        }
    }
}
  • 1.关于销毁的内容在这里不做分析,只关注与我们三步曲中的关键步骤
  • 2.self.run这个代码最终由Producer 延伸到我们具体的事务代码 AnonymousObservable.run
final private class AnonymousObservable<Element>: Producer<Element> {
    //这里同样省略了些代码...

    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)
    }
}
  • 1.let sink = AnonymousObservableSink()声明了一个sink对象
  • 2.sink.run(self)这个写法很好,把业务进行向下分发,使分工更加的明确
final private class AnonymousObservableSink<Observer: ObserverType>: Sink<Observer>, ObserverType {
    //这里同样省略了些代码...

    func run(_ parent: Parent) -> Disposable {
        parent.subscribeHandler(AnyObserver(self))
    }
}
  • 1.parent是上一步传入的self->AnonymousObservable对象
  • 2.我们非常兴奋的看到 AnonymousObservable.subscribeHandler,从这句代码我们解惑了为什么我们的序列订阅的时候流程会执行我们 序列闭包,然后去执行 发送响应
  • 3.这里还有一个比较重要的东西AnyObserver(self)
public struct AnyObserver<Element> : ObserverType {
        //这里同样省略了些代码...

    public init<Observer: ObserverType>(_ observer: Observer) where Observer.Element == Element {
        self.observer = observer.on
    }

    //这里同样省略了些代码...
}

在这个构造方法里面,我们创建了一个结构体 AnyObserver 保存了一个信息 AnonymousObservableSink.on 函数,不是 AnonymousObservableSink,,很重要~!!!!!!!!

发送响应

根据我们上面的分析:

observer.onNext("Rx发送信号")其实就等于AnyObserver ().onNext("Rx发送信号")
这时发现AnyObserver没有这个方法,不过按照作者的思路,我们在其父类中寻找,或者协议中寻找

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))
    }
    
    /// Convenience method equivalent to `on(.completed)`
    public func onCompleted() {
        self.on(.completed)
    }
    
    /// Convenience method equivalent to `on(.error(Swift.Error))`
    /// - parameter error: Swift.Error to send to observer(s)
    public func onError(_ error: Swift.Error) {
        self.on(.error(error))
    }
}

外界 observer.onNext("Rx发送信号") 再次变形 :AnyObserver.on(.next("Rx发送信号")) ,这里一定要主要,这个AnyObserver调用了 on 里面传的是 .next函数, .next函数带有我们最终的参数

public struct AnyObserver<Element> : ObserverType {
    /// Anonymous event handler type.
    public typealias EventHandler = (Event<Element>) -> Void

    private let observer: EventHandler

    /// Construct an instance whose `on(event)` calls `eventHandler(event)`
    ///
    /// - parameter eventHandler: Event handler that observes sequences events.
    public init(eventHandler: @escaping EventHandler) {
        self.observer = eventHandler
    }
    
    /// Construct an instance whose `on(event)` calls `observer.on(event)`
    ///
    /// - parameter observer: Observer that receives sequence events.
    public init<Observer: ObserverType>(_ observer: Observer) where Observer.Element == Element {
        self.observer = observer.on
    }
    
    /// Send `event` to this observer.
    ///
    /// - parameter event: Event instance.
    public func on(_ event: Event<Element>) {
        self.observer(event)
    }

    /// Erases type of observer and returns canonical observer.
    ///
    /// - returns: type erased observer.
    public func asObserver() -> AnyObserver<Element> {
        self
    }
}
  • 我们分析过self.observer = observer.on = self.observer = AnonymousObservableSink.on,那么这里的self.observer(event) = AnonymousObservableSink.on(event),其中event = .next("Rx发送信号"),看到这里不禁对RxSwift说一句 “卧槽~牛逼!”

总结:

1:序列概念 万物皆序列(编码统一) ,随时随地享用
2:通过函数式思想吧一些列的需求操作下沉(把开发者不关心的东西封装) - 优化代码,节省逻辑


Rxswift核心流程图
RxSwift核心详解.png

最后一句:创作不易,如果对各位大佬有帮助,请留下你们的小星星✨

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

推荐阅读更多精彩内容