测试代码:
let dispose = Observable<Int>.create { (observer) -> Disposable in
observer.onNext(1)
observer.onCompleted()
return Disposables.create()
}.subscribe(onNext: { (i) in
print("\(i)")
}, onError: { (error) in
print("\(error)")
}, onCompleted: {
print("complete")
})
过程解析
创建源
关系如图,方框里的是类,上层的方框表示是父类,箭头表示持有关系。所以:
- 匿名源继承自 Producer
- 匿名源持有创建源的闭包 handler
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)
}
}
创建观察者
匿名观察者的创建:
let observer = AnonymousObserver<Element> { 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()
}
}
匿名观察者:
final class AnonymousObserver<Element>: ObserverBase<Element> {
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)
}
}
ObserverBase:
class ObserverBase<Element> : Disposable, ObserverType {
private let _isStopped = AtomicInt(0)
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)
}
}
}
func onCore(_ event: Event<Element>) {
rxAbstractMethod()
}
func dispose() {
fetchOr(self._isStopped, 1)
}
}
- 匿名观察者继承自 ObserverBase
- 匿名观察者持有 handler,但是这个 handler 不是调用者给的那3个闭包(subscribe, onError, onCompleted),handler 的参数是 event,在 handler 中,根据 event 类型,分别调用了那3个闭包
订阅
订阅方法:
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()
}
let callStack = Hooks.recordCallStackOnError ? Hooks.customCaptureSubscriptionCallstack() : []
// 省略掉匿名观察者的初始化,上面有
return Disposables.create(
self.asObservable().subscribe(observer),
disposable
)
}
Disposables.create 返回的是 BinaryDisposable。
它就是持有了两个 Disposable,并且同步处理两个Disposable,该 dispose 时一起 dispose,该释放时一起释放,就是把两个 Disposable 合并成一个了。
self.asObservable().subscribe(observer) 调用的方法是匿名源的订阅方法,这个方法定义在 Producer 中:
class Producer<Element> : Observable<Element> {
override func subscribe<Observer: ObserverType>(_ observer: Observer) -> Disposable where Observer.Element == Element {
// 只保留了重要的代码
let disposer = SinkDisposer()
let sinkAndSubscription = self.run(observer, cancel: disposer)
disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink, subscription: sinkAndSubscription.subscription)
return disposer
}
}
这里面又用到了 SinkDisposer,SinkDisposer 保存了一个 Sink,和一个 Subscription,这个就有点迷惑了,Sink 和 Subscription 都是 Disposable 类型,那它们两个什么含义呢?SinkDisposer 是什么作用呢
接下来调用到的 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)
}
这里又出来一个匿名源Sink:
final private class AnonymousObservableSink<Observer: ObserverType>: Sink<Observer>, ObserverType {
typealias Element = Observer.Element
typealias Parent = AnonymousObservable<Element>
// state
private let _isStopped = AtomicInt(0)
override init(observer: Observer, cancel: Cancelable) {
super.init(observer: observer, cancel: cancel)
}
func on(_ event: Event<Element>) {
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 {
return parent._subscribeHandler(AnyObserver(self))
}
}
代码基本上贴完了,这些东西我看了非常久才看得透彻。
从闭包到响应式编程
创建源步骤中得到的是匿名源对象,并且之后调用的订阅方法也是它的,但其实观察者订阅到的源并不是它。
毕竟源并不是一个闭包那么简单的,它还要管理它的状态。
从 AnonymousObservableSink 的这段代码可以看出:
func run(_ parent: Parent) -> Disposable {
return parent._subscribeHandler(AnyObserver(self))
}
是 AnyObserver 订阅的匿名源,而 AnyObserver 没做什么特别的,它就只是保存一个 EventHandler 类型的闭包,有消息来时,它再调用这个闭包,也就是把 AnonymousObservableSink 包装成观察者类型。
而观察者是被 AnonymousObservableSink 拿着的。
对象的持有关系是这样的:
- 匿名源 持有 SubscribeHandler
- SubscribeHandler 持有 AnyObserver
- AnyObserver 持有 EventHandler
- EventHandler 是 AnonymousObservableSink 的方法
- AnonymousObservableSink 持有 Observer
所以当事件发生时,事件的传递过程是这样:
匿名源->AnonymousObservableSink->Observer
所以从闭包到响应式编程是通过 AnonymousObservableSink 做到的,AnonymousObservableSink 把自己伪装成观察者,并且持有想订阅匿名源的观察者。
那为什么要在匿名源和观察者之间强行加个小三儿呢,因为这个小三替匿名源管理了状态,当 error/completed 发生时,AnonymousObservableSink 就会调用 它持有的 _cancel 的 dispose 方法,并把自己的状态设置成 disposed,以后再接收到消息,它也不会向下传递了。
所以我认为 Sink 的作用就是桥接命令式编程和响应式编程的,但是它的作用是不是仅限于源,我还得打个问号。
而 _cancel 就是 SinkDisposer。(一会儿再讲)
观察者的转换过程比较简单,通过 ObserverBase 控制的状态。
从内存角度看看
从xcode的 memory graph 可以看出持有关系:
- BinaryDispoable 被 disposeBag 持有
- SinkDisposer 和 匿名源Sink 互相引用
- 还有源和观察者的 Dispose 没有被显示出来,因为 Dispose 是结构体,不需要管理内存
源被 SinkDisposer +16 持有,这是个什么东西?我翻遍了 SinkDisposer,也没找到持有源的地方。
于是测试:
var observable: Observable<Int>? = nil
observable = Observable<Int>.create { (observer) -> Disposable in
observer.onNext(1)
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
// 在这里打断点, 看看 1s 之后,源还在不在
observer.onCompleted()
}
let dispose = Disposables.create()
return dispose
}
if let o = observable {
let dispose = o.subscribe(onNext: { (i) in
print("\(i)")
}, onError: { (error) in
print("\(error)")
}, onCompleted: {
print("complete")
})
dispose.disposed(by: disposeBag)
}
}
发现在一秒钟之后,源已经被释放了。
那就先不考虑上面的 SinkDisposer +16,搞不好是SinkDisposer的run方法也未可知呀
每个类型都是什么作用
- 匿名源:保存 SubscribeHandler
- Producer:匿名源需要把 SubscribeHandler 转换成源,但是这个事情不仅仅是匿名源需要的,其他类也会需要的,所以就把转换的方法提取成 Producer 类。但是 Producer 没办法包揽一切,还是需要匿名源决定怎么转换的,匿名源是通过重写 Producer 的 run 方法处理转换的。
- 匿名源Sink:但是为了保持匿名源的纯净,转换工作是匿名源Sink在做的,匿名源只是在 run 中调用匿名源 Sink,并把处理结果给 Producer。匿名源Sink中处理了 stop 状态
- 观察者和 ObserverBase 没什么好说的
- BinaryDisposable:当 disposeBag 被销毁时,dispose() 要从 BinaryDisposable 开始调起,传给观察者、观察者的源,所以就用二叉Disposable 把它们包在一起
- SinkDisposer:Sink 的 Disposer,它持有 sink 和 源的 dispose,会同时调用两者的 dispose(),跟BinaryDisposable 有点类似
这里面 SinkDisposer 和 BinaryDisposable 显得有点奇怪,以下是我的理解:
dispose消息来源有两个:DisposeBag 销毁时发出的,和源发出的。
1. DisposeBag 销毁时 要通知到:源的 dispose,观察者的 dispose,源(注意不通知观察者)
用 BinaryDisposable 保存 观察者的 dispose 方法 和 SinkDisposer
Sink 我们前面的理解是:对于外面来说,可以认为它就是源,所以 SinkDisposer 就可以认为是源的 disposer,它是用来 dispose 源的。它保存了源的 dispose 和 匿名源Sink(直接认为就是源吧)
匿名源是帮匿名源处理状态的,它收到 dispose() 后就会改改自己的状态。
2. 源发出 complete 或者 error 时 要通知到:源的 dispose,观察者的 dispose,源、观察者
disposebag销毁时,是直接调用dispose方法通知到各方的,源发出complete或者error 是通过 on(event:) 方法传递的。
源发出消息,到了匿名源sink这里,它会改改自己的状态并把消息传给观察者。
观察者收到event后,也会改改自己的状态,然后调用观察者的dispose方法。
还差源的dispose方法没有调用,匿名源sink持有sinkDisposer,会通知到sinkDisposer的。
咦?那不就有一个循环了:匿名源sink调用SinkDisposer的dispose,SinkDisposer又会在它的dispose方法里调用匿名源sink的dispose。
是滴,的确是这样,不过在SinkDisposer和匿名源sink里都有状态判断,状态是已dispose的话,就不会再调用下去了。
Sink/Dispose 是什么
- Sink 是 SubscribeHandler 和 观察者的桥梁,它的主要作用是管理源的状态
- subscription 应该都是 Disposable 类型的,是订阅后源的dispose,dispose里一般做的事情都是:当取消订阅时,源会做一些回收工作,或者更改状态