RxSwift: 麻烦给个人爱人来一个 DisposeBag


上篇文章 mojito: 麻烦给个人爱人来一份 RxSwiftgit

没有说起 DisposeBag 回收机制github

缘由有其二api

一是由于安全

时间过短,我没来及看bash

二是由于闭包

文章过长,必口腔溃疡ide


Disposable

话很少说,来的都是回头客post

看一下经典案例fetch

let obable = Observable<String>.create { observer -> Disposable in
    observer.onNext("dispose")   # step1
    observer.onCompleted()       # step2
    return Disposables.create {
        print("Disposables 释放") # step6
    }
}

 _ = obable.subscribe(onNext: { (str) in
    print("序列" + str) # step3
 }, onError: { _ in
 }, onCompleted: {
    print("完成回调")   # step4
 }, onDisposed: {
    print("销毁回调")   # step5
 })
 // 打印顺序 序列dispose -> 完成回调 -> 销毁回调 ->  Disposables 释放
复制代码

Q 1: 为何订阅建立时 闭包返回值是 Disposable 类型 ?ui

先理清一些概念

Disposable

# 名为 Disposable 的协议,定义一个重要的方法 dispose
public protocol Disposable {
    # 处理 回收资源.
    func dispose()
}
复制代码

Disposables

# Disposables 是 结构体
public struct Disposables {
    private init() {}
}

# Disposables 扩展 create,返回值 AnonymousDisposable 对象
# 销毁者1
extension Disposables {
    public static func create(with dispose: @escaping () -> Void) -> Cancelable {
        return AnonymousDisposable(disposeAction: dispose)
    }
}
复制代码

Disposables.create,建立了 匿名销毁者 AnonymousDisposable对象, 将闭包 step6 传入

返回值是 Cancelable类型

# 名为 Cancelable 的协议,继承 Disposable
public protocol Cancelable : Disposable {
    # 资源是否被销毁过.
    var isDisposed: Bool { get }
}
复制代码

再看一下 AnonymousDisposable

# 继承了 DisposeBase 和 Cancelable,同时拥有 isDisposed & dispose()
private final class AnonymousDisposable : DisposeBase, Cancelable {
    # Disposables.create 建立的闭包
    public typealias DisposeAction = () -> Void

    private let _isDisposed = AtomicInt(0)
    private var _disposeAction: DisposeAction?
    # 是否被销毁
    public var isDisposed: Bool {
        return isFlagSet(self._isDisposed, 1)
    }
    # 保存闭包
    private 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()
            }
        }
    }
}
复制代码

AtomicInt(0): 继承 NSLock, 赋值原始值为 0

fetchOrisFlagSet 都是 AtomicInt 类 的方法,都是线程安全


isFlagSet

func isFlagSet(_ this: AtomicInt, _ mask: Int32) -> Bool {
    return (load(this) & mask) != 0
}
# 当 `self._isDisposed` 不为0 的时候,也就是 被销毁过
# 则 isFlagSet 返回 true,即 isDisposed 为true 
复制代码

fetchOr

func fetchOr(_ this: AtomicInt, _ mask: Int32) -> Int32 {
    this.lock()
    let oldValue = this.value
    this.value |= mask
    this.unlock()
    return oldValue
}
# 进行 位运算 | ,只有当第一次为 0 的时候,返回 oldValue 0 
# 外界等式 成立
# newValue 为 位运算以后的值 1,下次等式 就不等于 0 
# 目的:只销毁一次
复制代码

dispose()

if let action = self._disposeAction {
    self._disposeAction = nil
    action()
}
# 临时变量 action 保存 外界闭包
# 外界闭包 置nil 
# 执行闭包
复制代码

到这里,咱们小结一下

  • 小结
    • Disposables.create_subscribeHandler闭包执行回调时,开始执行的
    • 当 执行 _subscribeHandler,势必产生一个匿名销毁者 AnonymousDisposable
    • AnonymousDisposable 实例,持有外界 销毁闭包
    • AnonymousDisposable,具备 销毁的能力且只会销毁一次,以及 是否销毁的判断

销毁者继承链以下:


Disposables

看到这里就产生了第二个问题

Q 2: dispose何时调用 ?


时间回溯到 上篇的 subscribe

public func subscribe(onNext: ((Element) -> Void)? = nil, onError: ((Swift.Error) -> Void)? = nil, onCompleted: (() -> Void)? = nil, onDisposed: (() -> Void)? = nil)
    -> Disposable {
        let disposable: Disposable
        # 将外界传入的 onDisposed 闭包 , 即 print("销毁回调") 
        # 生成 匿名销毁者 AnonymousDisposable 实例 
        if let disposed = onDisposed {
            disposable = Disposables.create(with: disposed)
        } else {
            disposable = Disposables.create()
        }
        
        let observer = AnonymousObserver<Element> { event in
        switch event {
            ...省略
            case .error(let error):
                disposable.dispose()
            case .completed:
                disposable.dispose()
            }
        }
        # 又 return 一个 Disposables.create
        return Disposables.create(
            self.asObservable().subscribe(observer),
            disposable # 销毁者2 onDisposed
        )
    }
复制代码

不难看出,外界调用 subscribe 的时候,将 onDisposed 闭包传入

subscribe 的返回值 也是 Disposable类型,也是经过 Disposables.create 返回

定睛一看

这个 Disposables.create, 有2个参数


奇怪的事情发生了

点进去

extension Disposables {
    # 经过2个销毁者 ,生成一个新的销毁者
    public static func create(_ disposable1: Disposable, _ disposable2: Disposable) -> Cancelable {
        return BinaryDisposable(disposable1, disposable2)
    }
}
复制代码

不是看在一个爹的份上,你祖坟今天可能没了

Disposables.creat 销毁者1 说到


BinaryDisposable 销毁者,和以前分析的 AnonymousDisposable 一模一样,这里就不分析了

private final class BinaryDisposable : DisposeBase, Cancelable {
    .... 
    # 只是内部多了一个参数
    var isDisposed: Bool {
        return isFlagSet(self._isDisposed, 1)
    }
    
    func dispose() {
        if fetchOr(self._isDisposed, 1) == 0 {
            self._disposable1?.dispose()
            self._disposable2?.dispose()
            self._disposable1 = nil
            self._disposable2 = nil
        }
    }
}
复制代码

问题又来到了这个 二元销毁者 的第一个参数 self.asObservable().subscribe(observer)

能够在 Producer中 找到它的身影

override func subscribe<Observer: ObserverType>(_ observer: Observer) -> Disposable where Observer.Element == Element {
        # 管道清洁工
        # 返回一个 disposer 实例,在它释放时,释放管道内 全部引用
        let disposer = SinkDisposer()
        
        # 把 disposer 和 订阅者 传入 序列AnonymousObservable 的 run 中
        let sinkAndSubscription = self.run(observer, cancel: disposer)
        disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink, subscription: sinkAndSubscription.subscription)
        return disposer
}
复制代码

建立了一个 管道清洁工 SinkDisposer 实例 disposer ,经过调用 AnonymousObservable 的 run,将生成的 sinksubscription分别持有

并返回 disposer


AnonymousObservable

final private class AnonymousObservable<Element>: Producer<Element> {
    override func run<Observer: ObserverType>(_ observer: Observer, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where Observer.Element == Element {
        # 经过上面传入的 销毁者,和订阅者 生成匿名观察管道 
        let sink = AnonymousObservableSink(observer: observer, cancel: cancel)
        # 调用run ,也就是 执行 _subscribeHandler 闭包 ,将返回值 赋值给subscription
        # subscription 指的是 销毁者1
        let subscription = sink.run(self)
        return (sink: sink, subscription: subscription)
    }
}
复制代码

AnonymousObservableSink 继承于 Sink,Sink 一样继承于 Disposable,表明了 AnonymousObservableSink 一样具备 dispose() 的能力


老师,我晕了

能不能把 DisposeBag 先给我

我吐一下


Q 3: AnonymousObservableSinkSinkDisposer 之间的关系是什么?

A 3: SinkDisposer 将本身的实例,经过匿名观察序列,传入 管道 AnonymousObservableSink 中,管道 Sink 拥有最终解释权


意味着当外界执行订阅subscribe的时候, 会creat 一个 Disposables 元祖

Disposables 元祖内包含 :

  • onDisposed 销毁者2
  • 管道清洁工 SinkDisposer
    • sink
      • AnonymousObservableSink
    • subscription
      • 销毁者1


由于加入了 Sink 的概念,Sink 做为转换者,处理了 序列 和订阅者 以及 销毁者之间的联系

若是把 Sink 比做 一栋大厦

SinkDisposer 就是大厦内的清洁工 ,SinkDisposer 负责处理大厦一切 杂物,但调度能力及解释权仍是归大厦 Sink 所属


SinkDisposer

private final class SinkDisposer: Cancelable {
    private enum DisposeState: Int32 {
        case disposed = 1
        case sinkAndSubscriptionSet = 2
    }
    # 初始值为 0
    private let _state = AtomicInt(0)
    private var _sink: Disposable?
    private var _subscription: Disposable?
    # 外界先设置 setSinkAndSubscription
    func setSinkAndSubscription(sink: Disposable, subscription: Disposable) {
        self._sink = sink
        self._subscription = subscription
        
        # 0 | 2 ,第一次返回oldValue 0,previousState 为 0
        # _state 赋值为 2
        let previousState = fetchOr(self._state, DisposeState.sinkAndSubscriptionSet.rawValue)
        
        # 第一次 previousState 为0, 0 & 2 = 0,继续走
        if (previousState & DisposeState.sinkAndSubscriptionSet.rawValue) != 0 {
            rxFatalError("Sink and subscription were already set")
        }
        
        # 0 & 1 = 0,不进 if
        if (previousState & DisposeState.disposed.rawValue) != 0 {
            sink.dispose()
            subscription.dispose()
            self._sink = nil
            self._subscription = nil
        }
    }

    # 销毁时调用,上面方法已走过一次
    func dispose() {
        # 在初次调用 setSinkAndSubscription 后, _state 为2, 2 | 1 = 3, fetchOr 返回旧值 2 ,_state 变为 3
        # previousState 为 2
        let previousState = fetchOr(self._state, DisposeState.disposed.rawValue)
        
        # 2 & 1 = 0,不进 if, 继续走
        if (previousState & DisposeState.disposed.rawValue) != 0 {
            return
        }

        # 2 & 2 = 2, 知足条件,进 if ,分别 dispose
        if (previousState & DisposeState.sinkAndSubscriptionSet.rawValue) != 0 {
            # AnonymousObservableSink 调用 dispose
            sink.dispose() 
            # 销毁者1 调用 dispose
            subscription.dispose()
            # 销毁后,分别置nil
            self._sink = nil
            self._subscription = nil
        }
    }
}
复制代码

Q A

Q 1: 为何订阅建立时 闭包返回值是 Disposable 类型 ?


Disposable 类型 指的是 匿名销毁者,即销毁者1。由于想在序列建立的时候,就给它挖好坟墓,立好墓碑

所说

我于杀戮之中盛放,亦如黎明中的花朵

死不重要,帅就完事了


Q 2: dispose何时调用 ?


在本文中,显式调用了 onCompleted,即 执行 subscribeonCompleted闭包,而且接着 调用

disposable.dispose()

case .completed:
    onCompleted?()
    disposable.dispose() # 销毁者2
}
复制代码

即 打印顺序为 完成回调 -> 销毁回调

而 此时的 发出onCompleted 信号,必然会顺着 水管 流到 AnonymousObservableSink,调用 sink 的on,即

case .error, .completed:
    if fetchOr(self._isStopped, 1) == 0 {
        self.forwardOn(event)
        self.dispose() # 调用父类 Sink 的 dispose,父类调用 SinkDisposer 的 dispose
    }
}
复制代码

那么这时 SinkDisposer 就会对 sink 和 销毁者1 ,进行销毁

因此最后打印 销毁者1 的 闭包 -> Disposables 释放


执行顺序细节

这里衍生出 Q 4: 若是不显 式 调用 onCompleted 呢? 改成

let obable = Observable<String>.create { observer -> Disposable in
    observer.onNext("dispose")
    // observer.onCompleted()
    return Disposables.create {
         print("Disposables 释放")
    }
}
let dispose  = obable.subscribe(onNext: { (str) in
    print("序列" + str)
}, onError: { _ in
    print("错误回调")
}, onCompleted: {
    print("完成回调")
}, onDisposed: {
    print("销毁回调")
})
# 显式调用 dispose
dispose.dispose()
复制代码

这时候就会先调用 SinkDisposer 的dispose, 元祖 BinaryDisposable 你们还记得吧,SinkDisposer 会先调用,而销毁者2 onDisposed 后调用

因此打印为 序列dispose -> Disposables 释放 -> 销毁回调


Q 4 都有了 Q 5 还会远吗?

Q 5: 为何调用了 dispose 就能够销毁 响应了呢?

由于 咱们销毁了 Sink,销毁了大厦,销毁了通讯管道,销毁了外卖小哥送外卖的地址

还怎么响应呢 ?

固然了,序列 和 观察者,终究是 iOS 里面的 平凡的实例对象,会随着控制器的生命周期而销毁


听到这里

懂了的扣 1

不懂的扣脚


DisposeBag

RxSwift 还有一种垃圾回收方式, DisposeBag 能够称之为 垃圾袋

能够把它想象成 一个 autoReleasePool

里面装满了销毁者

随着你把 DisposeBag 扔进垃圾桶,也就是控制器的生命周期结束

里面的销毁者也就逐一销毁


rx.disposeBag

由于 NSObject+Rx 对 垃圾袋 进行了优雅的拓展 ,咱们不须要本身建立 disposeBag 了

viewModel.title.asDriver()
 .drive(titleLabel.rx.text)
 .disposed(by: rx.disposeBag)

# 只需调用 rx.disposeBa 便可
# pod 'NSObject+Rx', '~> 5.0' # https://github.com/RxSwiftCommunity/NSObject-Rx
复制代码

感兴趣的能够本身看一下 rx.disposeBag 的源码


以上是我对 DisposeBag 的理解,还请不吝指正

但愿你喝完这 2杯 mojito 味道的 RxSwift 以后

再也不须要垃圾袋

相关文章
相关标签/搜索