(十七)RxSwift之Disposable

307 阅读5分钟

Disposable - 可被清除的资源

一个序列如果发出了 error 或者 completed 事件,那么所有内部资源都会被释放。如果需要提前释放这些资源或取消订阅的话,那么可以手动调用 dispose 方法。

下面我们来看一段熟悉的代码(手动调用)

let ob = Observable<Any>.create { (obserber) -> Disposable in
    //发送信号
    obserber.onNext("马小撂")
    return Disposables.create{print("销毁闭包")}
}

//订阅信号
let dispose = ob.subscribe(onNext: { (text) in
    print("on next\(text)")
}, onError: { (error) in
    print("error")
}, onCompleted: {
    print("完成")
}) {
    print("销毁回调")
}

dispose.dispose()
  • 首先先看observable的创建,里面返回一个销毁着

Disposables.create{print("dispose销毁")}

点进去看见disposables的创建

public static func create(with dispose: @escaping () -> Void) -> Cancelable {
    return AnonymousDisposable(disposeAction: dispose)
}

这里面返回了一个AnonymousDisposable

fileprivate final class AnonymousDisposable : DisposeBase, Cancelable {

    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()
            }
        }
    }
}

AnonymousDisposable初始化的时候保存了一个创建Disposables时的回调闭包,和一个dispose()的方法,解释一下fetchOr方法

func fetchOr(_ this: AtomicInt, _ mask: Int32) -> Int32 {
    this.lock()
    let oldValue = this.value
    this.value |= mask
    this.unlock()
    return oldValue
}

this.value 初始化的时候为0,this.value 赋值给 oldValue,然后 this.value 按位或 mask(1)this.value等于1,返会 oldValue(0),再次进来是this.value等于1,返回1不等于0,所有闭包的销毁方法只会执行一次。

  • 然后在让我们来看一下序列的订阅,点进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()
        }
        
        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()
            }
        }
        return Disposables.create(
            self.asObservable().subscribe(observer),
            disposable
        )
}

subscriber会创建一个Disposable,如果外界传过来闭包就保存创建,没有就直接创建。在subscriberHandle里面我还可以看见当发送error事件和completed事件时会帮我们调用dispose()

我们着重来看一下self.asObservable().subscribe(observer),disposable 这句返回Disposables的创建

public static func create(_ disposable1: Disposable, _ disposable2: Disposable) -> Cancelable {
    return BinaryDisposable(disposable1, disposable2)
}

这里面返回了一个二元销毁着BinaryDisposable

private final class BinaryDisposable : DisposeBase, Cancelable {

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

初始化保存了两个销毁着,并在dispose()方法中全部销毁置空。

接下来,我们看一下二元销毁着的两个参数是什么,第二个参数非常的直观,就是上面创建保存外界闭包的销毁着,那第一个参数是什么呢? 点击subscribe就会来到父类Producersubscribe函数,

override func subscribe<Observer: ObserverType>(_ observer: Observer) -> Disposable where Observer.Element == Element {
if !CurrentThreadScheduler.isScheduleRequired {
}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
    }
}

可以清晰的看到返回的是SinkDisposer,这就是我们二元销毁者的第一个参数。初始化一个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)
}

返回一个sinkAnonymousObservableSink) 和subscriptionAnonymousDisposable)这个元组,带着这两个参数会来到setSinkAndSubscription函数中

fileprivate final class SinkDisposer: Cancelable {
fileprivate enum DisposeState: Int32 {
    case disposed = 1
    case sinkAndSubscriptionSet = 2
}

private let _state = AtomicInt(0)
private var _sink: Disposable?
private var _subscription: Disposable?

var isDisposed: Bool {
    return isFlagSet(self._state, DisposeState.disposed.rawValue)
}

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

在这个函数中,保存了sinksubscription,因为0按位或为2,但返回的旧值,仍为0,0&其他都是0,所以下面的方法都不走

最后当我们手动调用dispose.dispose()时会发生什么

func dispose() {
    if fetchOr(self._isDisposed, 1) == 0 {
        self._disposable1?.dispose()
        self._disposable2?.dispose()
        self._disposable1 = nil
        self._disposable2 = nil
    }
}

我们看到了二元销毁者,逐一的销毁并置nil,先看第一个参数SinkDisposer的销毁

case disposed = 1
case sinkAndSubscriptionSet = 2
func dispose() {
    let previousState = fetchOr(self._state, DisposeState.disposed.rawValue)

    if (previousState & DisposeState.disposed.rawValue) != 0 {
        return
    }

    if (previousState & DisposeState.sinkAndSubscriptionSet.rawValue) != 0 {
        guard let sink = self._sink else {
            rxFatalError("Sink not set")
        }
        guard let subscription = self._subscription else {
            rxFatalError("Subscription not set")
        }

        sink.dispose()
        subscription.dispose()

        self._sink = nil
        self._subscription = nil
    }
}

经过上次的处理self._state已经为2了:

第一个条件:2 & 1 == 0,不满足,跳过继续下一步。

第二个条件成立:2 & 2 == 2,然后让_sink_subscription分别去disposeAnonymousObservableSink继承于Sink,就会来到Sinkdisposed

func dispose() {
    fetchOr(self._disposed, 1)
    self._cancel.dispose()
}

_sinkfetchOr做了个标记后,让SinkDisposer调用dispose。上次新值value为3了,那它与上任何一个枚举值都是true,所以第一个条件满足,直接return。 然后是_subscriptionAnonymousDisposable)的dispose

fileprivate func dispose() {
    if fetchOr(self._isDisposed, 1) == 0 {
        if let action = self._disposeAction {
            self._disposeAction = nil
            action()
        }
    }
}

把销毁回调闭包置为nil,然后执行打印销毁闭包,第一个参数就结束了,然后来看第二个参数就是订阅时初始化的销毁闭包,调用一下就可以了,打印销毁回调

这个销毁流程,可以看出我们通过销毁sink,来达到销毁的目的。

前面说过如果发出了 error 或者 completed事件会自动调用,但是调用的顺序会有所不同

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()
    }
}

先发送self.forwardOn(event),然后调用self.dispose()

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()
    }
}

先调用AnonymousObserver中的闭包,也就是订阅中的回调闭包,然后在调用sink中的闭包。