iOS探索RxSwift之销毁者

1,536 阅读4分钟

一、销毁者

RxSwift销毁者扮演了很重要的作用,销毁已经完成(completed)的或者已经错误(error)的序列。但是如果你需要提前释放这些资源或者取消订阅的话,那么你可以对返回的 Disposable(可被清除的资源)  调用 dispose 方法。 调用 dispose 方法后,订阅将被取消,并且内部资源都会被释放掉。

1.销毁者初探

接下来我们来看一个例子:

        //创建序列
        self.intervalOB = Observable<Int>.interval(.seconds(1), scheduler: MainScheduler.init())
        //订阅事件-返回销毁者
        let dispose = self.intervalOB.subscribe(onNext: { num in
            self.showSencondNum.text = String(num)
            print("num=\(num)")
        })
        _ = self.stopAction.rx.tap.subscribe(onNext: {
            print("点击按钮")
            dispose.dispose() //执行销毁方法
        })

看到例子,1.创建了定时器序列 2.订阅并返回了Disposable(可被清除的资源) 3.点击按钮执行dispose()销毁方法。

运行结果: image.png 我们在看一个例子:

        // 创建序列
        let ob = Observable<Any>.create { observer -> Disposable in
            observer.onNext("NY")
            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()

看到代码创建序列Observable 中返回了销毁者Disposables.create,然后订阅ob返回Disposable(可被清除的资源),在最后调用dispose.dispose()清理资源。

现在有一个问题Disposables.create返回的是什么?有什么作用?

进入代码一探究竟: image.png

image.png

public class DisposeBase {
    init() {
#if TRACE_RESOURCES
    _ = Resources.incrementTotal()
#endif
    }
    
    deinit {
#if TRACE_RESOURCES
    _ = Resources.decrementTotal()
#endif
    }
}

//协议类
public protocol Cancelable : Disposable {
    /// Was resource disposed.
    var isDisposed: Bool { get }
}
public protocol Disposable {
    /// Dispose resource.
    func dispose()
}
//在子类实现
/// 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 基础了DisposeBase基类,并实现了Cancelable 协议方法isDisposed,dispose 。dispose 私有方法不可重写,保存临时action 并销毁self.disposeAction = nil 在执行闭包action()。

继续跟踪代码:

func fetchOr(_ this: AtomicInt, _ mask: Int32) -> Int32 {
    this.lock()
    let oldValue = this.value
    this.value |= mask  // 0000 0000 | 0000 0001  结果是1
    this.unlock()
    return oldValue
}

判断self.disposed==0时执行并销毁self.disposeAction。

2.销毁的本质

我们运行一下例子二: image.png 从打印的信息上看出,订阅到了消息,执行了执行完毕后dispose.dispose(),在销毁前执行了,释放后在执行了销毁回调。

如果修改代码:

        // 创建序列
        let ob = Observable<Any>.create { observer -> Disposable in
            observer.onNext("NYY-e")
            observer.onCompleted()
            observer.onNext("XXXX")
            return Disposables.create { print("销毁释放了") }
        }
        ////省略代码............////
        print("执行完毕")
        //        dispose.dispose()

从代码上看,onCompleted()后又再次,发送了消息onNext("XXXX"),如果onCompleted 执行完已经销毁了序列,将看不到打印。 image.png 和我们的猜想差不多,在onCompleted()之后序列执行完成Completed回调后,销毁回调,在销毁释放了。

问题1:
不执行dispose.dispose(),而执行observer.onCompleted() 的销毁执行顺序是不一样的。
问题2:
为什么会产生这样的差异,第一先执行释放,再销毁回调。第二先回调,再释放。

进入源码一探究竟: image.png

    public static func create(_ disposable1: Disposable, _ disposable2: Disposable) -> Cancelable {
        BinaryDisposable(disposable1, disposable2)
    }
    
    
    //二元销毁者
    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
        }
    }
}

func dispose() 和AnonymousDisposable 的dispose 基本一样,也是只销毁一次,可以外部调用。

return Disposables.create(
                self.asObservable().subscribe(observer),//SinkDisposer
                disposable //外界的销毁闭包
      )

image.png

这个sinkAndSubscription.sink 和 sinkAndSubscription.subscription 的作用是什么? image.png sinkAndSubscription.sink 就是AnonymousObservableSink

sinkAndSubscription.subscription 就是 Disposable(销毁者)对象处理闭包

所以销毁Sink在Rx世界失去联系,真正要销毁的是RxSwift响应式关系

3.垃圾袋销毁流程

看垃圾袋代码:

extension Disposable {
    /// Adds `self` to `bag`
    ///
    /// - **parameter** bag: `DisposeBag` to add `self` to.
    public func disposed(by bag: DisposeBag) {
        bag.insert(self) //添加到垃圾袋
    }
}

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() //类销毁时调用
    }
    

DisposeBag->insert(序列)->dispose遍历执行(销毁响应关系)->先保存,在移除removeAll->设置isDisposed = true。

4.总结

  1. Disposable销毁者:就是创建AnonymousDisposable中的dispose 基本一样,也是只销毁一次,可以外部调用,sinkAndSubscription 在AnonymousDisposable 订阅中创建,sinkAndSubscription 控制销毁,序列的响应关系。
  2. DisposeBag垃圾袋:就是收集和管理需要释放的序列,(添加到array,遍历释放)就是这样简单的逻辑。