美文网首页
RxSwift-dispose源码解析

RxSwift-dispose源码解析

作者: yahibo | 来源:发表于2019-08-06 19:03 被阅读0次

    任何对象都有生命周期,有创建就要销毁。 OC中有initdeallocswiftinitdeinitRxSwift也不例外,RxSwiftcreatedispose。下面就看看dispose是如何管理序列销毁的。

    一篇没有配图的文章是没有灵魂的😂

    disposable.png

    通过前面了解了RxSwift的两种清除方式:

    • 订阅产生的可清除资源(Disposable)对象,调用dispose方法清除
    • 通过清除包DisposeBag清除,在作用域结束后被释放,也可以在需要的时候置空释放

    无论哪种方式,最终都是调用dispose()方法来释放。

    下面看一段序列由创建到销毁:

    //创建一个序列
    let ob = Observable<Any>.create { (observer) -> Disposable in
            observer.onNext("msg")
            return Disposables.create{
                print("被销毁")
            }
        }
    //订阅序列
    let dis = ob.subscribe(onNext: { (val) in
            print(val)
        }){
            print("销毁了")
    }
    //销毁订阅
    dis.dispose()
    

    此处代码,我们调用了dispose方法来销毁对象,销毁者dis其实和创建序列时返回的Disposables对象并不是一个对象。

    disposable对象创建代码:

    extension Disposables {
        public static func create(with dispose: @escaping () -> Void) -> Cancelable {
            return AnonymousDisposable(disposeAction: dispose)
        }
    }
    
    • 实质上创建了一个AnonymousDisposable类型的销毁者对象
    • 传入了业务层的监听闭包,销毁对象时用来通知
    fileprivate final class AnonymousDisposable : DisposeBase, Cancelable {
        public typealias DisposeAction = () -> Void
    
        private var _isDisposed = AtomicInt(0)
        private var _disposeAction: DisposeAction?
    
        public var isDisposed: Bool {
            return isFlagSet(&self._isDisposed, 1)
        }
    
        fileprivate init(disposeAction: @escaping DisposeAction) {
            self._disposeAction = disposeAction
            super.init()
        }
        fileprivate func dispose() {
            if fetchOr(&self._isDisposed, 1) == 0 {
                if let action = self._disposeAction {
                    self._disposeAction = nil
                    action()
                }
            }
        }
    }
    
    • 初始化保存业务层,创建销毁者对象实现的闭包
    • dispose()为销毁方法,该方法调用后就销毁了传入的闭包对象
    • 判断实列是否被释放,未释放就执行执行对保存闭包的置空操作
    • action()通知业务层释放监听闭包,通知完成出{}作用域action即被释放

    再看看订阅者中的销毁者的创建(代码标记为1️⃣):

    public func subscribe(onNext: ((E) -> 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() : []
            
            let observer = AnonymousObserver<E> { 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(
                self.asObservable().subscribe(observer),
                disposable
            )
    }
    
    • onDisposed外部实现的销毁者闭包,实现即传入闭包,否则直接调用create()创建,目的是对外发出销毁通知
    • 最后又创建了一个销毁者对象并返回,可在业务层做销毁操作,该销毁对象保存了self.asObservable().subscribe(observer)返回的销毁者,和当前方法中创建的销毁者。what???搞毛啊,这么多销毁者,怕我还不够迷糊吗!!

    销毁者Disposables有多种扩展,为满足不同需求:

    1. 需要在序列创建处观察销毁情况;
    2. 前面几篇文章有讲到,在调用onErroronCompleted方法会销毁我们的序列,在业务层省去了开发人员去销毁序列的步骤;
    3. 根据不同业务需求,需要满足开发人员销毁序列的功能。

    因此以上出现了这么多的销毁者,最终销毁者还是被同类销毁者(不同扩展)所管理。看一下最后一个销毁者内部做了哪些事情:

    extension Disposables {
        public static func create(_ disposable1: Disposable, _ disposable2: Disposable) -> Cancelable {
            return BinaryDisposable(disposable1, disposable2)
        }
    }
    
    • 收集前面所创建的销毁者到BinaryDisposable对象中
    private final class BinaryDisposable : DisposeBase, Cancelable {
    
        private var _isDisposed = AtomicInt(0)
    
        // state
        private var _disposable1: Disposable?
        private var _disposable2: Disposable?
    
        /// - returns: Was resource disposed.
        var isDisposed: Bool {
            return isFlagSet(&self._isDisposed, 1)
        }
    
        init(_ disposable1: Disposable, _ disposable2: Disposable) {
            self._disposable1 = disposable1
            self._disposable2 = disposable2
            super.init()
        }
    
        func dispose() {
            if fetchOr(&self._isDisposed, 1) == 0 {
                self._disposable1?.dispose()
                self._disposable2?.dispose()
                self._disposable1 = nil
                self._disposable2 = nil
            }
        }
    }
    
    • 继承了Disposable协议,并实现了协议方法dispose()

    该类中实现了dispose()方法,该方法即是外部订阅后调用的dispose()方法,销毁所有创建序列时产生的销毁者,销毁之前各自掉用各自的dispose方法,来销毁外界保留的闭包对象,并向业务层发送销毁通知。

    下面看一下代码1️⃣处self.asObservable().subscribe(observer)的销毁者是如何产生的:

    class Producer<Element> : Observable<Element> {
        override init() {
            super.init()
        }
    
        override func subscribe<O : ObserverType>(_ observer: O) -> Disposable where O.E == Element {
            if !CurrentThreadScheduler.isScheduleRequired {
                // The returned disposable needs to release all references once it was disposed.
                let disposer = SinkDisposer()
                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
                }
            }
        }
    }
    

    又是我们熟悉的Producer,熟悉的sink,在该处创建了一个SinkDisposer对象,应该又是一个销毁者:

    fileprivate final class SinkDisposer: Cancelable {}
    
    • 继承自Cancelable -> Disposable,并实现了dispose()方法
    • 销毁者去向run -> AnonymousObservableSink -> Sink
    • Sink继承自Disposable,实现了dispose()方法,内部调用了外部传入的销毁者即SinkDisposer对象

    setSinkAndSubscription该方法传入了sink销毁者和业务层创建序列时创建的销毁者。代码如下:

    func setSinkAndSubscription(sink: Disposable, subscription: Disposable) {
        self._sink = sink
        self._subscription = subscription
    
        let previousState = fetchOr(&self._state, DisposeState.sinkAndSubscriptionSet.rawValue)
        if (previousState & DisposeState.sinkAndSubscriptionSet.rawValue) != 0 {
            rxFatalError("Sink and subscription were already set")
        }
    
        if (previousState & DisposeState.disposed.rawValue) != 0 {
            sink.dispose()
            subscription.dispose()
            self._sink = nil
            self._subscription = nil
        }
    }
    

    保存了两个销毁者(Producer创建的销毁者、业务层创建的销毁者),这个地方其他的没干就是想销毁这两个销毁者:

    sink.dispose()
    subscription.dispose()
    self._sink = nil
    self._subscription = nil
    

    置空前都调用了dispose(),这里面置空销毁者,并向业务层发送了销毁通知。

    sink主要用来连接序列,触发序列闭包,向观察者发送消息。而sink清空所有内部销毁者后并置空,序列和订阅者就失去联系。

    系统销毁:

    AnonymousObservableSink -> Sink -> dispose() -> SinkDisposer -> dispose()

    外部销毁:

    BinaryDisposable -> AnonymousObservableSink -> Sink -> dispose() -> SinkDisposer -> dispose()

    无论是系统销毁,还是外部调用dispose销毁最终所有产生的销毁者都会被销毁释放。到此我们发现我们所销毁的居然是外部对应的监听闭包,内部创建的Disposable的子类对象。

    sink连接了序列和订阅者,sink本身是Disposable对象,因此被销毁后断开了序列和订阅者之间的联系。

    相关文章

      网友评论

          本文标题:RxSwift-dispose源码解析

          本文链接:https://www.haomeiwen.com/subject/uaowdctx.html