注: 本系列所有代码基于RxSwift v6.5.0
前言
作为本系列的开篇,有必要介绍下RxSwift
:
RxSwift
是Swift
函数响应式编程的一个开源库,由Github
的ReactiveX
组织开发、维护。RxSwift
的目的是让数据/事件流和异步任务能够更方便的序列化处理,能够使用Swift
进行响应式编程。
好的,以上是官方解释,下面从开发角度诠释下这个问题:
- 易复合,比如将各种
UI
控件的响应事件以闭包的形式整合到创建代码块里,而不是单独调用方法。既方便代码的维护,又可以直接获取目标元素,比如获取当前响应的Button
。 - 风格统一,当我们进行多人开发时候。统一风格的代码会让我们少很多烦恼。对于代码维护、
Review
都是最好的选择。 Rx
能够完美的支持单元测试,无论你的项目是否需要这么做。但是,当你需要时候,它就在那里。- 对于基于
MVVM
架构的项目来说,进行双向绑定是一个很繁琐的问题,而Rx
能够完美的解决这个问题,可以通过管道化的方案,直接进行数据和组件的绑定。
核心流程
好的,进入正题。RxSwift
本质上就是信号的产生、订阅、发送跟销毁。核心逻辑就是产生、订阅、发送三步曲:
1、创建可观察序列(信号)
2、订阅信号
3、发送信号
看代码:
// 1. 创建可观察序列
let ob = Observable<Any>.create { observer in
// 3. 发送信号
observer.onNext("test")
return Disposables.create()
}
// 2. 订阅信号
let _ = ob.subscribe(onNext: { str in
print(str)
}).disposed(by: disposeBag)
以上代码就实现了信号的创建、订阅、发送的整个过程,有熟悉RAC
的读者就会一眼看出,这不就是RACSignal
的执行流程么。是的,在设计上,它们是一致的。都完成了管道包装到信号发送的过程。接下来逐步分析下该过程在Rx
内部是怎么实现的。
创建可观察序列(信号)
Observable
的create
方法实质上是调用了Create
文件(RxSwift
包里的文件名,方便读者查找)里的create
方法:
public static func create(_ subscribe: @escaping (AnyObserver<Element>) -> Disposable) -> Observable<Element> {
AnonymousObservable(subscribe)
}
实质上就是调用了Create
文件里的AnonymousObservable
类的构造方法,这个类持有一个subscribeHandler
的逃逸闭包,正是我们上边传入的subscribe
,即发送信号的闭包。
final private class AnonymousObservable<Element>: Producer<Element> {
typealias SubscribeHandler = (AnyObserver<Element>) -> Disposable
// 发送信号的闭包
let subscribeHandler: SubscribeHandler
init(_ subscribeHandler: @escaping SubscribeHandler) {
self.subscribeHandler = subscribeHandler
}
...
}
此时,我们已经完成了创建的过程,只是将发送信号的闭包保存在内部的Observable
对象里。
订阅信号
由上文可观察到订阅信号的实质是调用了ob
的subscribe
方法,这个方法在ObservableType+Extensions
文件里:
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() : []
// 1、创建observer对象
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(
// 2、 调用ob对象的subscribe。
self.asObservable().subscribe(observer),
disposable
)
}
上边的代码主要做了两件事情:
- 创建
observer
对象。
这里的observer
对象要区别于上文的observable
(观察者和被观察者)。AnonymousObserver
类以尾随闭包的形式被创建为observer
。观察下其代码:
final class AnonymousObserver<Element>: ObserverBase<Element> {
typealias EventHandler = (Event<Element>) -> Void
private let eventHandler : EventHandler
init(_ eventHandler: @escaping EventHandler) {
#if TRACE_RESOURCES
_ = Resources.incrementTotal()
#endif
self.eventHandler = eventHandler
}
override func onCore(_ event: Event<Element>) {
self.eventHandler(event)
}
#if TRACE_RESOURCES
deinit {
_ = Resources.decrementTotal()
}
#endif
}
其构造函数将传入的内容保存为eventHandler
存储在该对象里。创建observer
对象里进行了代码转换,这里先不做解析,留作下文说明。
- 调用
ob
对象的subscribe
当去AnonymousObservable
类查找时候,并没有发现这个方法,通过继承关系,发现实质上是调用了其父类Producer
(在Producer
文件中)的subscribe
方法。顾名思义,这正是生产者消费者模式的一种体现。父类负责生产,交由子类消费。看具体代码:
override func subscribe<Observer: ObserverType>(_ observer: Observer) -> Disposable where Observer.Element == Element {
if !CurrentThreadScheduler.isScheduleRequired {
let disposer = SinkDisposer()
// 1. 具体调用
let sinkAndSubscription = self.run(observer, cancel: disposer)
disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink, subscription: sinkAndSubscription.subscription)
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的地方就是方法的具体流向,即调用了其run
方法,虽然Producer
中也标明了次方法。但在AnonymousObservable
类里重写了该方法,导致真正的调用会在create
文件中AnonymousObservable
类中进行,此时看到这个类好熟悉,不就是创建信号时候调用的类么?
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)
}
run
方法通过一个AnonymousObservableSink
的下沉类,调用run(self)
。观察这个下沉类的run
方法:
func run(_ parent: Parent) -> Disposable {
parent.subscribeHandler(AnyObserver(self))
}
而这个parent
只是AnonymousObservable
的别名而已:
typealias Parent = AnonymousObservable<Element>
即run(self)
就是调用了AnonymousObservable
对象的subscribeHandler
,也就是创建信号时期传递的发送信号的闭包,此时,也就完成了信号的订阅工作。
发送信号
在上文中,在订阅信号的时候,最终就会执行发送信号的闭包。所以在发送信号的过程中,仅仅需要关注发送的信号是如何回调到订阅时期的 onNext、onError、onCompleted
这些方法里即可。
发送信号的过程,以上文中的 observer.onNext("text")
为例。根据ObserverType
文件中的代码:
public func onNext(_ element: Element) {
self.on(.next(element))
}
public func onCompleted() {
self.on(.completed)
}
public func onError(_ error: Swift.Error) {
self.on(.error(error))
}
可知,其实质是调用了相应的on
方法,传入枚举值。对于observer
来说,AnonymousObserver
并没有直接重写该方法,而是放在其父类ObserverBase
中重写了该方法:
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)
}
}
}
这样转化的实质会调用到onCore
方法,onCore
方法也就是在AnonymousObserver
中具体执行的方法:
final class AnonymousObserver<Element>: ObserverBase<Element> {
typealias EventHandler = (Event<Element>) -> Void
private let eventHandler : EventHandler
init(_ eventHandler: @escaping EventHandler) {
#if TRACE_RESOURCES
_ = Resources.incrementTotal()
#endif
self.eventHandler = eventHandler
}
// 通过event, 执行构造函数传递过来的闭包
override func onCore(_ event: Event<Element>) {
self.eventHandler(event)
}
#if TRACE_RESOURCES
deinit {
_ = Resources.decrementTotal()
}
#endif
}
此时,拉回我们的视角,还记得上文我们在创建observer
对象的时候,没有详细分解其代码,此时再来看:
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()
}
}
显然, self.onCore(event)
在observer
的构建闭包里执行,比如next
最终会调用到 onNext?(value)
,这里的onNext
不正是订阅信号传递进来的闭包,执行这个方法,在订阅里边就得到了回调。
小结
总体原则遵守创建、订阅、发送、回调。通过继承关系实现方法的相互调用。