響應式編程是RxSwift的核心思想,統一思想快速開發。同樣在ReactiveX系列中其他語言也都使用了這一思想,當我們掌握了RxSwift
運用,那么RxJava
,RxPHP
,RxJs
等等都能夠快速上手。那么RxSwift
是如何響應的呢?下面就來看一下源碼都做了哪些事情。
RxSwift核心流程
先看一下是如何使用的,代碼如下:
//1、創建序列
let obs = Observable<Any>.create { (observer) -> Disposable in
//3、發送信號
observer.onNext("我是一條消息")
return Disposables.create()
}
//2、訂閱序列
obs.subscribe(onNext: { (val) in
//4、序列監聽
print("onNext:\(val)")
}).disposed(by: disposeBag)//5、打包待銷毀
- 通過
Observable
的create
創建序列,在create
閉包內調用onNext
方法實現信號發送 - 調用
subscribe
方法訂閱序列,并實現subscribe
的參數閉包onNext
,在閉包內監聽信號 - 最后通過
disposed
對序列打包等待銷毀
看到代碼可能會疑惑,消息是如何發給訂閱者的。按正常邏輯,訂閱后才能收到信息,那么可以猜測,在成為訂閱者并布置好監聽后,訂閱者向序列發送了一條消息,通知可觀察序列可以發信號了。大致可整理為如下流程:
以上只是猜測,下面來看具體的代碼實現。在RxSwift
中同名的方法有很多,很難做到直接定位代碼位置,我們可以通過command+點擊
配合斷點一步步找到對應方法的底層實現。
1、創建序列
public static func create(_ subscribe: @escaping (AnyObserver<E>) -> Disposable) -> Observable<E> {
return AnonymousObservable(subscribe)
}
該方法是對ObservableType
協議的擴展,最外層實現的閉包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<O : ObserverType>(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == Element {
let sink = AnonymousObservableSink(observer: observer, cancel: cancel)
let subscription = sink.run(self)
return (sink: sink, subscription: subscription)
}
}
首先看一下AnonymousObservable
的繼承鏈如下:
- AnonymousObservable -> Product -> ObservableType -> ObservableConvertible
在父類Product
中好像有我沒需要的方法:
override func subscribe<O : ObserverType>(_ observer: O) -> Disposable where O.E == Element {
}
像是訂閱方法,但不是,但也有著千絲萬縷的聯系。到此為止,序列創建部分已完成,可總結如下:
-
create
方法實現參數閉包,內部創建AnonymousObservable
對象 -
AnonymousObservable
對象保存了外界實現的閉包 -
Producer
中的subscribe
方法,應該是訂閱后將要調用的方法
記住以上三點,后序逐一對比。
2、訂閱序列
根據方法名找到subscribe
的實現,command+點擊
直接進入實現,源碼如下(取部分源碼):
public func subscribe(onNext: ((E) -> Void)? = nil, onError: ((Swift.Error) -> Void)? = nil, onCompleted: (() -> Void)? = nil, onDisposed: (() -> Void)? = nil)
-> Disposable {
//此處省略若干行代碼
let observer = AnonymousObserver<E> { event in
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
)
}
該方法是對ObservableType
的拓展。在方法內部已經出現對觀察者的定義,AnonymousObserver
類型的閉包observer
。
源碼分析:
2.1、observer
內部調用的外部(應用層)實現的閉包,由此看出所有信號是由此發出,event
是observer
的參數,不難看出,observer
閉包也是在其他地方調用,傳入帶有信號值的event
參數
2.2、observer
被當做參數傳入到subscribe
中,而observer
的調用必然是在subscribe
中實現的
self.asObservable().subscribe(observer)
2.3、self.asObservable()
該方法返回本身,保證協議的一致性,方法如下:
public class Observable<Element> : ObservableType {
// 省去代碼若干
public func asObservable() -> Observable<E> {
return self
}
}
2.4、繼續斷點執行找到subscribe
方法,正是上面所提到的Producer
中的方法,方法如下:
override func subscribe<O : ObserverType>(_ observer: O) -> Disposable where O.E == Element {
// 省去代碼若干
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
}
}
2.5、緊接著我的observer
觀察者被傳入到run
中,上面說到該觀察者一定會被調用,繼續深入
let sinkAndSubscription = self.run(observer, cancel: disposer)
2.6、繼續斷點執行,發現self.run
的調用,調用的是AnonymousObservable
中的run
方法,代碼如下:
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<O : ObserverType>(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == Element {
let sink = AnonymousObservableSink(observer: observer, cancel: cancel)
let subscription = sink.run(self)
return (sink: sink, subscription: subscription)
}
}
2.7、此處就是創建序列時的AnonymousObservable
類。在run
方法類創建了sink
對象,在初始化時傳入了我們上面所說的觀察者,記住sink
保存了觀察者observer
閉包,并且調用了sink.run(self)
方法,傳入的是創建時產生的可觀察序列observable
閉包對象,深入run
:
final private class AnonymousObservableSink<O: ObserverType>: Sink<O>, ObserverType {
typealias E = O.E
typealias Parent = AnonymousObservable<E>
// 省去代碼若干
// 此處向父類Sink初始化了observer對象
override init(observer: O, cancel: Cancelable) {
super.init(observer: observer, cancel: cancel)
}
func run(_ parent: Parent) -> Disposable {
return parent._subscribeHandler(AnyObserver(self))
}
}
2.8、撥開云霧見天日,此處parent
由let subscription = sink.run(self)
傳入,self
即為創建序列create
方法返回的observable
對象,而_subscribeHandler
是創建序列所保存的閉包,此時我們的閉包就被調用了,被調用閉包如下:
let obs = Observable<Any>.create { (observer) -> Disposable in
//3、發送消息
observer.onNext("我是一條消息")
return Disposables.create()
}
發送信號的閉包被調用,接下來就是信號發送了。
3、發送信號
根據上面步驟繼續探索,代碼已經執行到我們的業務層。
在信號發送閉包中通常調用一下三種方法,用來發送信號。如下:
-
observer.onNext("我是一條消息")
信號發送 -
observer.onCompleted()
序列完成,完成后序列將被釋放 -
observer.onError(error)
序列出錯中斷,序列不可繼續使用,被釋放
以上三個方法為ObserverType
的拓展方法
extension ObserverType {
/// Convenience method equivalent to `on(.next(element: E))`
///
/// - parameter element: Next element to send to observer(s)
public func onNext(_ element: E) {
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))
}
}
-
E
表示了一個泛型信號量,可表示任意類型的信號 -
.next(element)
是一個帶泛型參數的枚舉,管理了三種類型事件的消息傳遞。如下:
public enum Event<Element> {
/// Next element is produced.
case next(Element)
/// Sequence terminated with an error.
case error(Swift.Error)
/// Sequence completed successfully.
case completed
}
on
這是AnonymousObservableSink
中的方法,代碼如下:
final private class AnonymousObservableSink<O: ObserverType>: Sink<O>, ObserverType {
typealias E = O.E
typealias Parent = AnonymousObservable<E>
// 代碼省略若干行
func on(_ event: Event<E>) {
#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()
}
}
}
}
內部根據Event
枚舉不同成員變量做不同的信號發送,信號發送調用了forwardOn
方法。方法實現如下:
class Sink<O : ObserverType> : Disposable {
init(observer: O, cancel: Cancelable) {
self._observer = observer
self._cancel = cancel
}
final func forwardOn(_ event: Event<O.E>) {
if isFlagSet(&self._disposed, 1) {
return
}
self._observer.on(event)
}
}
代碼有些長只保留了核心部分,Sink
即AnonymousObservableSink
的父類,見上文2.7處描述
,_observer
即是訂閱中在內部產生的AnonymousObserver
對象,而該對象調用了on
方法并傳遞了信號。on
方法所在位置如下:
- AnonymousObserver -> ObserverBase -> on()
class ObserverBase<ElementType> : Disposable, ObserverType {
typealias E = ElementType
func on(_ event: Event<E>) {
switch event {
case .next:
if load(&self._isStopped) == 0 {
self.onCore(event)
}
case .error, .completed:
if fetchOr(&self._isStopped, 1) == 0 {
self.onCore(event)
}
}
}
}
在方法內部又掉用了self.onCore(event)
,此時該方法在AnonymousObserver
中實現,代碼如下:
final class AnonymousObserver<ElementType> : ObserverBase<ElementType> {
typealias Element = ElementType
typealias EventHandler = (Event<Element>) -> Void
private let _eventHandler : EventHandler
init(_ eventHandler: @escaping EventHandler) {
self._eventHandler = eventHandler
}
override func onCore(_ event: Event<Element>) {
return self._eventHandler(event)
}
}
源碼分析
- 此處通過
_eventHandler
來發送信號,_eventHandler
是從哪來的呢?逆推onCore
調用者是observer
,而observer
是訂閱時在內部創建的,被一層層傳入到此 - 而在
observer
初始化時即被保存為
_eventHandler
,_eventHandler
調用即調用了訂閱時創建的observer
閉包,進而信號又通過閉包內的閉包傳出到業務層
//2、訂閱序列
obs.subscribe(onNext: { (val) in
print("onNext:\(val)")
}).disposed(by: disposeBag)
天呢!容我喘口氣~~
至此我們響應式編程的創建、訂閱、發送、接收等流程就已完成。整個流程會覺得很復雜,但它統一了所有事件的創建與監聽,統一思想快速開發,今后的開發流程就是:
- 創建序列 -> 訂閱序列 -> 發送序列 -> 響應序列
sink在Rx中充當管理者,管理序列,觀察者和銷毀者,將序列發送至觀察者,并管理銷毀者適時消耗序列,回收資源。
最后附上兩張總結圖: