Rx|Rx 生命周期管理

about sequence 先引用下官方文档:
Here is a sequence of numbers:

--1--2--3--4--5--6--| // terminates normally

Another sequence, with characters:
--a--b--a--a--a---d---X // terminates with error

Some sequences are finite while others are infinite, like a sequence of button taps:
---tap-tap-------tap--->

序列从生命周期来讲分为两种: 有限序列和无限序列, 有限序列以complete或者error结束,而无限序列永远都不会发送complete或者error事件。
首先明确一点观察者的生命周期肯定是要比被观察者的生命周期要长的,不然怎么观察呢,如果观察者都死掉了,被观察者还在干活,那你怎么观察呢?
对于有限序列还比较好办,在序列结束的时候发个通知告诉观察者就可以了罗。
对于无限序列呢?怎么去管理它的生命周期呢?既要保证观察者的生命周期比被观察者长,又要在恰当的时候销毁掉它。
有限序列
// AnonymousObservableSink.onfunc on(_ event: Event) { #if DEBUG _synchronizationTracker.register(synchronizationErrorMessage: .default) defer { _synchronizationTracker.unregister() } #endif switch event { case .next: if _isStopped == 1 { return } forwardOn(event) case .error, .completed: if AtomicCompareAndSwap(0, 1, &_isStopped) { forwardOn(event) dispose() } } }

有限序列在onError或者onComplete的时候,触发dispose操作。
无限序列 无限序列就比较麻烦了,先分析下类的归属问题
// Producer.subscribelet disposer = SinkDisposer() let sinkAndSubscription = run(observer, cancel: disposer) disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink, subscription: sinkAndSubscription.subscription)return disposer

// AnonymousObservable.run override func run(_ 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) }

SinkDisposer 持有 Sink 和 Subscription
AnonymousObservableSink持有 SinkDisposer 和 Observer
看上去有点不太理解,没关系对应下面这个具体例子:
Observable.create { observer -> Disposable in observer.onNext("hello") return Disposables.create() } .subscribe { event in print(event.element) }

SinkDisposer 持有 AnonymousObservableSink 和
{ observer -> Disposable in observer.onNext("hello") return Disposables.create() }

闭包产生的Disposable
AnonymousObservableSink: 持有 SinkDisposer 和
.subscribe { event in print(event.element) }

闭包产生的AnonymousObserver.
这样的话Sink持有SinkDisposer, SinkDisposer又持有Sink形成闭环,循环引用下内存永远不会释放。
验证设想 有限序列
func testObservable(){ Observable.create { observer -> Disposable in observer.onNext("hello") observer.onCompleted() return Disposables.create() } .debug() .subscribe { event in print(event.element) } defer { print("testObservable end") }}

// output log 2018-09-20 15:05:18.695: AppDelegate.swift:134 (testObservable()) -> Event next(hello) Optional("hello") 2018-09-20 15:05:18.696: AppDelegate.swift:134 (testObservable()) -> Event completed nil 2018-09-20 15:05:18.696: AppDelegate.swift:134 (testObservable()) -> isDisposed testObservable end

在Debug模式下会跟踪observable的事件信息和生命周期,这里可以看到在completed情况下,成功触发dispose
无限序列
func testObservable(){ Observable.create { observer -> Disposable in observer.onNext("hello") return Disposables.create() } .debug() .subscribe { event in print(event.element) } defer { print("testObservable end") }}

2018-09-20 15:20:29.176: AppDelegate.swift:134 (testObservable()) -> subscribed 2018-09-20 15:20:29.177: AppDelegate.swift:134 (testObservable()) -> Event next(hello) Optional("hello") testObservable end

这里可以看到没有dispose,现在这种情况下已经造成内存泄漏,这块内存永远不会释放了。
这就是为什么官方推荐你使用下面这种写法的原因:
Observable.create { observer -> Disposable in observer.onNext("hello") //observer.onCompleted() return Disposables.create() } .debug() .subscribe { event in print(event.element) } .disposed(by: disposeBag)

通过DisposeBag管理观察者的生命的周期,DisposeBag使用数组存放Disposable,在被释放前,会调用所有Disposable.dispose操作,达到释放内存的目的。再来看看dispose具体干了些啥:
// SinkDisposer.dispose func dispose() { let previousState = AtomicOr(DisposeState.disposed.rawValue, &_state)if (previousState & DisposeStateInt32.disposed.rawValue) != 0 { return }if (previousState & DisposeStateInt32.sinkAndSubscriptionSet.rawValue) != 0 { guard let sink = _sink else { rxFatalError("Sink not set") } guard let subscription = _subscription else { rxFatalError("Subscription not set") }sink.dispose() subscription.dispose()_sink = nil _subscription = nil } }

【Rx|Rx 生命周期管理】首先SinkDisposer 会调用 sink.dispose()
subscription.dispose() 紧接着将其置空,置空之后这个引用环就解开了,自然对象就会被释放掉。
结论 在任何时候使用subscribe都必须将其加入到DisposeBag中,否则就有可能造成内存泄漏,这样还带来一个好处你无需关注序列到底是有限序列还是无限序列,反正内存会最终释放。

    推荐阅读