前言
使用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