RxSwift学习7_销毁者

196 阅读8分钟

前言

使用RxSwift来进行编码的时候,一般在最后都要进行销毁,或者放到垃圾桶里随类的销毁一切销毁,那么这个销毁到底进行了什么操作,销毁了什么,如何进行销毁的呢?本文主要来讲解RxSwift里的销毁者角色的底层逻辑。

什么是销毁者

先举个简单的dispose序列的例子

// 创建序列
        let ob = Observable<Any>.create { observer -> Disposable in
            observer.onNext("zdh")
            return Disposables.create { print("销毁释放了") }
        }
        // 序列订阅
        let dispose = ob.subscribe(onNext: { anything in
            print("订阅到了:(anything)")
        }, onError: { error in
            print("订阅到Error:(error)")
        }, onCompleted: {
            print("完成了")
        }) {
            print("销毁回调")
        }
        NSMutableArray(capacity: 10)//10  扩容10+10 上拉加载更多
        print("执行完毕")
        dispose.dispose()

在创建序列里的return Disposables.create { print("销毁释放了") }中的Disposables,可以简单认为这是销毁者的类,通过create创建了一个Disposable,那么create里到底做了什么,我们看下源码

源码

extension Disposables {

    /// Constructs a new disposable with the given action used for disposal.
    ///
    /// - parameter dispose: Disposal action which will be run upon calling `dispose`.
    public static func create(with dispose: @escaping () -> Void) -> Cancelable {
        AnonymousDisposable(disposeAction: dispose)
    }

}

源码里,create里面创建了一个匿名内部类AnonymousDisposable,而dispose是外面的闭包,作为参数传给AnonymousDisposable,继续看AnonymousDisposable的源码

private final class AnonymousDisposable : DisposeBase, Cancelable {
    public typealias DisposeAction = () -> Void

    private let disposed = AtomicInt(0)
    private var disposeAction: DisposeAction?

    /// - returns: Was resource disposed.
    public var isDisposed: Bool {
        isFlagSet(self.disposed, 1)
    }

    /// Constructs a new disposable with the given action used for disposal.
    ///
    /// - parameter disposeAction: Disposal action which will be run upon calling `dispose`.
    private init(_ disposeAction: @escaping DisposeAction) {
        self.disposeAction = disposeAction
        super.init()
    }

    // Non-deprecated version of the constructor, used by `Disposables.create(with:)`
    fileprivate init(disposeAction: @escaping DisposeAction) {
        self.disposeAction = disposeAction
        super.init()
    }

    /// Calls the disposal action if and only if the current instance hasn't been disposed yet.
    ///
    /// After invoking disposal action, disposal action will be dereferenced.
    fileprivate func dispose() {
        if fetchOr(self.disposed, 1) == 0 {
            if let action = self.disposeAction {
                self.disposeAction = nil
                action()
            }
        }
    }
}

AnonymousDisposable中的初始化器保存了之前传进来的闭包,即它的属性disposeAction保存了这个闭包,这个闭包就是{ print("销毁释放了") }

继承链

AnonymousDisposable继承自DisposeBase类和Cancelable协议

DisposeBase里面只是进行了引用计数的处理,内存管理最常规的管理

/// Base class for all disposables.
public class DisposeBase {
    init() {
#if TRACE_RESOURCES
    _ = Resources.incrementTotal()
#endif
    }
    
    deinit {
#if TRACE_RESOURCES
    _ = Resources.decrementTotal()
#endif
    }
}

Cancelable协议里面只有一个isDisposed,同时还遵循一个协议Disposable,而Disposable里面有个非常核心的方法dispose(),对一个销毁者来说的话最重要的是销毁,一般协议都会在子类中实现。

/// Represents disposable resource with state tracking.
public protocol Cancelable : Disposable {
    /// Was resource disposed.
    var isDisposed: Bool { get }
}

/// Represents a disposable resource.
public protocol Disposable {
    /// Dispose resource.
    func dispose()
}

dispoce()核心方法

AnonymousDisposable中就实现协议中的dispose()方法,并且该核心方法是

私有方法,不给外部感知,不允许重写,也就是说自己管理自己的生命周期

销毁和销毁回调的顺序

先将self.disposeAction赋给一个过渡常量action,然后将disposeAction置空再进行闭包调用,

self.disposeAction = nil与 action()的执行顺序也是很重要的,因为只能发生一次销毁行为,销毁时外部的闭包只会执行一次,由于闭包执行是需要耗时的所以为了保证闭包不重复执行,先将disposeAction置空在执行

fetchOr

@discardableResult
@inline(__always)
func fetchOr(_ this: AtomicInt, _ mask: Int32) -> Int32 {
    this.lock()
    let oldValue = this.value
    //这里是个或等于运算 0000 0000 |= 0000 0001 = 0000 0001
    //                0000 0001 |= 0000 0001 = 0000 0001
    this.value |= mask //这里是个或等于运算0000 0000 |= 0000 0001 = 0000 0001
    this.unlock()
    return oldValue
}

这里有一个锁的操作,和一个或等于的操作,如果mask是1,那么执行 this.value |= mask的话就保证了this.value都是1,第一次进来self.disposed是0,那么this的值是0 ,将0赋值给oldValue然后返回的是0,同时执行this.value |= mask这个时候this.value就是1了,之后的oldValue就都是1了,因此保证了只执行一次

判断是否已经销毁过了,确保只销毁一次

这个dispose方法是在什么时候进行调用,似乎在AnonymousDisposable里我们是没有看到的,我们一般都是订阅完之后再销毁的,因此猜测这个dispose() 方法在订阅里,下面开始分析subscribe()方法。

销毁了什么

subscribe中

源码

    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() : []
            
            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(
                self.asObservable().subscribe(observer),
                disposable
            )
    }

在.error和.completed中都有disposable.dispose(),这里就是调了这个dispose()方法

如果外部的创建序列时没有error或者completed响应,那么就得外部在序列订阅处直接调dispose()方法进行销毁,如下图:

回到subscribe中的Disposables.create中,先看下这个create的源码和BinaryDisposable的源码:

extension Disposables {

    /// Creates a disposable with the given disposables.
    public static func create(_ disposable1: Disposable, _ disposable2: Disposable) -> Cancelable {
        BinaryDisposable(disposable1, disposable2)
    }

}

/// Represents two disposable resources that are disposed together.
private final class BinaryDisposable : DisposeBase, Cancelable {

    private let disposed = AtomicInt(0)

    // state
    private var disposable1: Disposable?
    private var disposable2: Disposable?

    /// - returns: Was resource disposed.
    var isDisposed: Bool {
        isFlagSet(self.disposed, 1)
    }

    /// Constructs new binary disposable from two disposables.
    ///
    /// - parameter disposable1: First disposable
    /// - parameter disposable2: Second disposable
    init(_ disposable1: Disposable, _ disposable2: Disposable) {
        self.disposable1 = disposable1
        self.disposable2 = disposable2
        super.init()
    }

    /// Calls the disposal action if and only if the current instance hasn't been disposed yet.
    ///
    /// After invoking disposal action, disposal action will be dereferenced.
    func dispose() {
        if fetchOr(self.disposed, 1) == 0 {
            self.disposable1?.dispose()
            self.disposable2?.dispose()
            self.disposable1 = nil
            self.disposable2 = nil
        }
    }
}

Disposables.create中有两个参数

1、self.asObservable().subscribe(observer)

这个参数,看下subscribe方法返回的是什么,

可以看到返回的也是一个Disposable,这是个临时创建的SinkDisposer,然后传进给run方法中,这个run应该是子类AnonymousObservable里的run方法,那么传进去做了什么,源码可以看到是返回了一个元组,这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)
    }
func run(_ parent: Parent) -> Disposable {
        parent.subscribeHandler(AnyObserver(self))
    }

AnonymousObservableSink的父类是一个sink

元组中的元素分别是AnonymousObservableSink(observer: observer, cancel: cancel)内部匿名sink(用来沟通当前序列self、observer、cancel)和sink.run(self)方法返回的Disposable。这个parent.subscribeHandler(AnyObserver(self))注意了,就是创建序列create的那个闭包参数了,返回值就是我当前的接收者,也就是返回一个销毁者

回到subscribe方法中

disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink, subscription: sinkAndSubscription.subscription)这个句代码就是进行了sinkAndSubscription这个元组的销毁工作

//
    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
        }
    }

销毁了sink,整个RX世界就会失去联系

2、disposable

这个是外界的销毁闭包

BinaryDisposables

也有个dispose方法对外开放的,销毁也是只能销毁一次,为外部提供更多可能性。

小结

RxSwift中销毁者真正要销毁的是RxSwift的响应式关系,让其无法通信

垃圾袋DisposeBag

例子

我们经常将销毁者方法垃圾袋里随controller的销毁一起进行销毁

        self.intervalOB = Observable<Int>.interval(.seconds(1), scheduler: MainScheduler.init())
        
        self.intervalOB.subscribe(onNext: { num in
            self.showSencondNum.text = String(num)
        }).disposed(by: disposeBag)

查看disposed(by: disposeBag)的源码

extension Disposable {
    /// Adds `self` to `bag`
    ///
    /// - parameter bag: `DisposeBag` to add `self` to.
    public func disposed(by bag: DisposeBag) {
        bag.insert(self)
    }
}

DisposeBag

可以看到者disposed是Disposable的一个拓展方法,然后这个bag插入里一个self,那么这个self是谁,这个self就是序列,谁调就是谁,也就是我将要销毁的对象,而DisposeBag就是垃圾袋,那么这个bag销毁了,这个self也就跟着一起销毁了,这也就是垃圾袋的工作原理。insert说明bag有很多的销毁对想,那是怎么加进去的呐?我们看下这个DisoseBag的源码

public final class DisposeBag: DisposeBase {
    
    private var lock = SpinLock()
    
    // state
    private var disposables = [Disposable]()
    private var isDisposed = false
    
    /// Constructs new empty dispose bag.
    public override init() {
        super.init()
    }

    /// Adds `disposable` to be disposed when dispose bag is being deinited.
    ///
    /// - parameter disposable: Disposable to add.
    public func insert(_ disposable: Disposable) {
        self._insert(disposable)?.dispose()
    }

    // 重点
    private func _insert(_ disposable: Disposable) -> Disposable? {
        self.lock.performLocked {
            if self.isDisposed {
                return disposable
            }

            self.disposables.append(disposable)

            return nil
        }
    }

    /// This is internal on purpose, take a look at `CompositeDisposable` instead.
    private func dispose() {
        let oldDisposables = self._dispose()

        for disposable in oldDisposables {
            disposable.dispose()
        }
    }

    private func _dispose() -> [Disposable] {
        self.lock.performLocked {
            let disposables = self.disposables
            
            self.disposables.removeAll(keepingCapacity: false)
            self.isDisposed = true
            
            return disposables
        }
    }
    
    deinit {
        self.dispose()
    }
}

_insert方法有个递归锁保护线程安全的,可以先不用管,然后这个方法是传进一个Disposable让返回一个Disposable,先判空isDisposed,如果是已经要销毁大量就返回disposable,直接销毁否则就self.disposables.append(disposable),放进disposables集合中去,那么拿到这些集合该怎么去销毁,猜测会进行遍历销毁,然后我们可以看到这个类中有dispose(),里面就是进行了disposables的遍历,然后一个个进行dispose()方法进行销毁。

那么什么时候调用DisposeBag的dispose()呐!很明显是在deinit的时候调了self.dispose()方法,也就是跟随DisposeBag的销毁一起进销毁了。

_dispose

有一个点需要注意的,就是_dispose方法,它里面先用个临时变量把self.disposables接收,然后将disposables 都remove掉,再返回那个临时变量,并且加了锁,这么做可以不影响外部,同时减少依赖关系,这个写发很值得学习。

	 private func _dispose() -> [Disposable] {
        self.lock.performLocked {
            let disposables = self.disposables
            
            self.disposables.removeAll(keepingCapacity: false)
            self.isDisposed = true
            
            return disposables
        }
    }

总结

本文讲解了RxSwift中的销毁者角色,什么是销毁者,销毁者继承链:AnonymousDisposable继承自DisposeBase类和Cancelable协议,核心是 Cancelable里的 dispose()方法也就是 AnonymousDisposable中就实现协议中的dispose()方法,销毁了什么,RxSwift中销毁者真正要销毁的是RxSwift的响应式关系,让其无法通信,最后是与销毁操作息息相关的垃圾袋,该处理方式是为了让Rx操作跟随着控制器的销毁一起进行销毁。

拓展

KVO