iOS探索RxSwift核心续

2,411 阅读5分钟

一、RxSwift核心

1、observable订阅流程

RxObservable继承链: image.png Producer:Observable > subscribe > currentThreadScheduler > self.run() > setSinkAndSubscription()

subscribe:AnonymousObserver(内部观察者)<eventHandler> > [ObserverBase](on onCore dispose) > [ObserverType](on)

image.png

public class Observable<Element> : ObservableType {
    init() {
#if TRACE_RESOURCES
        _ = Resources.incrementTotal()
#endif
    }
    public func subscribe<Observer: ObserverType>(_ observer: Observer) -> Disposable where Observer.Element == Element {
        rxAbstractMethod()
    }
    public func asObservable() -> Observable<Element> { self }

    deinit {
#if TRACE_RESOURCES
        _ = Resources.decrementTotal()
#endif
    }
}
  • Observable实现了一个协议ObservableType,而且ObservableType协议继承自ObservableConvertibleType协议,所以在Observable中实现了两个协议方法:subscribeasObservable

  • subscribe方法没有具体实现的逻辑,需要子类去实现。

  • asObservable方法返回的是self,看似用处不大,其实不是这样的。asObservable是非常有用的,如果一类是Observable的子类,我们可以直接返回self,如果不是Observable的子类,我们可以通过重写这个协议方法来返回一个Observable对象,这样保证了协议的一致性。在使用的时候我们可以直接写类似self.asObservable().subscribe(observer)这样的代码,有利于保持代码的简洁性,是良好的封装性的体现。

  • _ = Resources.incrementTotal()_ = Resources.decrementTotal()这两行代码其实是RxSwift内部实现的一个引用计数。这部分内容我会在后面的文章中再详解。

AnonymousObservableSink 的作用

final private class AnonymousObservableSink<Observer: ObserverType>: Sink<Observer>, ObserverType {
    typealias Element = Observer.Element 
    typealias Parent = AnonymousObservable<Element>

    // state
    private let isStopped = AtomicInt(0)


    #if DEBUG
        private let synchronizationTracker = SynchronizationTracker()
    #endif

    override init(observer: Observer, cancel: Cancelable) {
        super.init(observer: observer, cancel: cancel)
    }

    func on(_ event: Event<Element>) {
        #if DEBUG
            self.synchronizationTracker.register(synchronizationErrorMessage: .default)
            defer { self.synchronizationTracker.unregister() }
        #endif
        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()
            }
        }
    }


    func run(_ parent: Parent) -> Disposable {
        parent.subscribeHandler(AnyObserver(self))
    }
}
  • AnonymousObservableSinkSink的子类,AnonymousObservableSink本身遵守ObseverType协议,与此同时实现了run方法,虽然没有实现subscribe方法,但是已经足够了,这样AnonymousObservableSink从某种程度来说也是Observable

  • AnonymousObservableSink是Observer和Observable的衔接的桥梁,也可以理解成管道。它存储了_observer和销毁者_cancel。通过sink就可以完成从Observable到Obsever的转变。

  • run方法中的这行代码parent._subscribeHandler(AnyObserver(self)) ,其中parent是一个AnonymousObservable对象。_subscribeHandler这个block调用,代码会执行到创建序列时的block。然后会调用发送信号的代码obserber.onNext("发送信号"),然后代码会经过几个中间步骤会来到AnonymousObservableSink类的on方法。

  • 其中AnyObserver(self) 中的 self 就是observer是一个函数(function)on 。

image.png 完善核心流程图: image.png

2、timer内部分析

我们常用的定时器:

  • NSTimer
  • GCD
  • CADiplayLink

直接上代码分析:

//创建定时器
timer = Timer.init(timeInterval: 1, target: self, selector: #selector(timerFire), userInfo: nil, repeats: true)
timer.fire()
RunLoop.current.add(timer, forMode: .common)//加入runloop

//函数式写法
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: { timer in
          print(timer)
        })

//GCD写法
gcdTimer = DispatchSource.makeTimerSource()
gcdTimer?.schedule(deadline: .now(), repeating: .seconds(1))
gcdTimer?.setEventHandler(handler: {
            print("hello GCD")
        })
gcdTimer?.resume()
gcdTimer?.suspend()
gcdTimer?.cancel()
gcdTimer = nil

//CADisplayLink写法
cadTimer = CADisplayLink写法(target: self, selector: #selector(timerFire))
cadTimer?.preferredFramesPerSecond = 1
cadTimer?.add(to: .current, forMode: .common)

那如果使用RxSwift要如何实现呢?如何保证定时器的精确性呢?

Observable<Int>.timer(.seconds(1), period: .seconds(1), scheduler: MainScheduler.instance)
            .subscribe { result in
                print(result)
            }
            .disposed(by: disposeBag)

image.png RxSwift的timer底层实现是GCD,我们看下源码: image.png Timer 序列分为两种类型.

  • 一次性执行: 创建一个 Observable 在一段延时后,产生唯一的一个信号.一般用于某些只需要执行一次的延迟操作.如超时判断.
  • 重复多次执行: 创建一个 Observable 在一段延时后,每隔一段时间产生一个信号.

跟踪点开timer

public static func timer(_ dueTime: RxTimeInterval, period: RxTimeInterval? = nil, scheduler: SchedulerType)
        -> Observable<Element> {
        return Timer(
            dueTime: dueTime,
            period: period,
            scheduler: scheduler
        )
    }

发现Timer 继承着Producer(生产者),在RxSwift 中,序列大部分都是继承者Producer的.我们在设计一些代码时,通过会让功能相似的类继承着同一基类BaseClass,这里可以理解为Producer就是这些序列的基类,在基类中实现了序列的一些基本操作.例如订阅功能Subscribe(). image.png 运行代码调试: image.png 发现self.period有值执行如上代码,创建执行TimerSink > sink.run() 然后继续进入代码(run() -> Disposable):

func run() -> Disposable {
        return self.parent.scheduler.schedulePeriodic(0 as Observer.Element, startAfter: self.parent.dueTime, period: self.parent.period!) { state in
            self.lock.performLocked {    // 使用递归锁,防止互斥 RecursiveLock 
                self.forwardOn(.next(state)) //发送消息 - 执行回调
                return state &+ 1 //state 加1
            }
        }
    }

继续跟踪断点: image.png 判断如果disposed值发送改变,大概意思就是如果开始执行回收了,则直接返回,不执行 on发送消息了。

归纳百川汇de->on函数

self.observer.on(event)这段代码就是执行(->onCore),回调闭包代码,就是我们上面分析的核心流程,作者的思想确实厉害,归纳百川回流大海=on

初步了解sink思想:(AnonymousObserver水管(管理者或者生产者) -> (不同的管道)sink -><实现ObserverType>)on 函数在根据不同的 Element 类型进行分发执行回调函数(.next .error .completed)。

补充:Observable的各种创建方式

// 首先来一个空的序列 - 本来序列事件是Int类型的,这里调用emty函数 没有序列,只能complete
print("******** empty ********")
let emtyOb = Observable<Int>.empty()
_ = emtyOb.subscribe(onNext: { number in
    print("订阅:", number)
}, onError: { error in
    print("error:", error)
}, onCompleted: {
    print("完成回调")
}) {
    print("释放回调")
}

// 单个信号序列创建
let array = ["NY_EDU", "YYDS"]
Observable<[String]>.just(array)
            .subscribe { event in
                print(event)
            }.disposed(by: disposeBag)
        _ = Observable<[String]>.just(array)
            .subscribe(onNext: { number in
                print("订阅:", number)
            }, onError: { error in
                print("error:", error)
            }, onCompleted: {
                print("完成回调")
            }) {
                print("释放回调")
            }
            
// 多个元素 - 针对序列处理
Observable<String>.of("NY_EDU", "YYDS")
            .subscribe { event in
                print(event)
            }.disposed(by: disposeBag)

// 字典
Observable<[String: Any]>.of(["name":"LG_EDU", "age":18])
            .subscribe { event in
                print(event)
            }.disposed(by: disposeBag)

// 数组
Observable<[String]>.of(["NY_EDU", "YYDS"])
            .subscribe { event in
                print(event)
            }.disposed(by: disposeBag)
            
// 从集合中获取序列:数组,集合,set 获取序列 - 有可选项处理 - 更安全
Observable<[String]>.from(optional: ["NY_EDU", "YYDS"])
            .subscribe { event in
                print(event)
            }.disposed(by: disposeBag)    

总结

RXSwift核心原理

  • 三部曲 :创建序列(observable) ,订阅序列,发送信号(消息)
  • 核心中的订阅流程:订阅subscribe->(创建AnonymousObserver点阅者,保存event闭包,创建AnonymousObservableSink 管道生产者) -AnonymousObservableSink:这个家伙干了很多事,我们称它大号下水管道,根据不同的需求分流到不同的(sink)管道。
  • on函数:AnyObserver.on('我胡汉三又回来了')遵循了ObservableType协议
  • 分发(发送响应):回调到具体的函数(.next .error .completed)代码块

然后我们用RxSwift.timer 定时器来分析了(内部实现原理):

  • Timer序列:分两种,一次性执行,重复多次执行。
  • Timer是GCD:DispatchSourceTimer实现的定时器。
  • forwardOn:最终回到AnyObserver.on 回调函数。