RxSwift之深入解析dispose源码的实现原理

举报
Serendipity·y 发表于 2022/02/16 23:43:19 2022/02/16
【摘要】 一、前言 任何对象都有生命周期,有创建就要销毁。OC 中有 init 和 dealloc,swift 有 init 和 deinit,RxSwift 也不例外,有 create 和 dispose。Rx...

一、前言

  • 任何对象都有生命周期,有创建就要销毁。OC 中有 init 和 dealloc,swift 有 init 和 deinit,RxSwift 也不例外,有 create 和 dispose。
  • RxSwift 有两种清除方式:
    • 订阅产生的可清除资源(Disposable)对象,调用 dispose 方法清除;
    • 通过清除包 DisposeBag 清除,在作用域结束后被释放,也可以在需要的时候置空释放。
  • 无论哪种方式,最终都是调用 dispose() 方法来释放。
  • 例如,现有如下代码,基础序列的创建和订阅:
	// 创建序列
    let ob = Observable<Any>.create { (observer) -> Disposable in
        observer.onNext("ABC")
        return Disposables.create { print("销毁释放")} // dispose.dispose()
    }
    // 序列订阅
    let dispose = ob.subscribe(onNext: { (anything) in
        print("订阅到:\(anything)")
    }, onError: { (error) in
        print("订阅到:\(error)")
    }, onCompleted: {
        print("完成")
    }) {
        print("销毁回调")
    }
    print("执行完毕")
    // 销毁序列
    dispose.dispose()

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 运行结果如下所示:
	订阅到:ABC
	执行完毕
	销毁释放
	销毁回调

  
 
  • 1
  • 2
  • 3
  • 4
  • 可以发现在调用 dispose.dispose() 后,先执行的创建序列的回调闭包 Disposables.create { print(“销毁释放”)},再执行 {print(“销毁回调”)},那么:
    • 为什么调用 dispose() 方法能够执行创建序列时的闭包呢?
    • 为什么是先执行创建序列的闭包,再执行后面的销毁回调闭包呢?
    • dispose() 方法到底是如何实现销毁序列的呢?销毁的是什么?

二、销毁者创建

  • 点进 Disposables.create,可以看到返回了一个匿名销毁者 AnonymousDisposable:
    public static func create(with dispose: @escaping () -> Void) -> Cancelable {
        return AnonymousDisposable(disposeAction: dispose)
    }

  
 
  • 1
  • 2
  • 3
	fileprivate final class AnonymousDisposable : DisposeBase, Cancelable {
	    public typealias DisposeAction = () -> Void
	
	    /// Constructs a new disposable with the given action used for disposal.
	    ///
	    /// - parameter disposeAction: Disposal action which will be run upon calling `dispose`.
	    fileprivate init(_ disposeAction: @escaping DisposeAction) {
	        self._disposeAction = disposeAction
	        super.init()
	    }
	}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 继续,可以看到在 AnonymousDisposable 里,对象初始化,将外界传入的闭包保存在_disposeAction 里:
	fileprivate init(_ disposeAction: @escaping DisposeAction) {
		self._disposeAction = disposeAction
		super.init()
	}

  
 
  • 1
  • 2
  • 3
  • 4
  • 那么在什么时候调用的呢?继续,可以看到下面的 dispose() 方法:
	// 核心逻辑
	fileprivate func dispose() {
	    if fetchOr(self._isDisposed, 1) == 0 {
	        if let action = self._disposeAction {
	            self._disposeAction = nil
	            action()
	        }
	    }
	}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 这里有个重要的方法,fetchOr(self._isDisposed, 1),它是一个单项标记手段,this.value 初值是 0,所以返回的 oldValue 也是 0。
    • 传的 mask 是 1,this.value |= mask 按位或运算,this.value 值变为 1;
    • 只有第一次调用 fetchOr,,返回的是 0 , 第二次以后,再调用 fetchOr,返回的都是1。
    func fetchOr(_ this: AtomicInt, _ mask: Int32) -> Int32 {
	    this.lock()
	    let oldValue = this.value  // 0  1
	    this.value |= mask    // 1 1
	    this.unlock()
	    return oldValue  // 0 1 1 1 1 1 1 1
	}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • fetchOr 调用一次后,_isDisposed 就会 变为 1,其实就是属性标记,保证 dispose() 只执行一次。它这个标记方法中,没有直接操作业务属性,所以不会产生依赖,并且使用的是位运算,更加快速。
  • dispose() 中,将 _disposeAction 保存到 action,清除 _disposeAction, 执行 action()。销毁的代码只执行一次,所以当前 _disposeAction 置为 nil 后,再执行尾随必包 action:
	// 核心逻辑
	fileprivate func dispose() {
	    if fetchOr(self._isDisposed, 1) == 0 {
	        if let action = self._disposeAction {
	            self._disposeAction = nil
	            action()
	        }
	    }
	}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

三、销毁 dispose() 方法调用

  • 上面的流程,是在 subscriberHandle 回调闭包中,在 subscriberHandle 之还有一个重要的订阅流程 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()
	            }
	}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 在 subsricbe 进入订阅方法内容,可以看到:在这里保存外界这个销毁提示的闭包:
	if let disposed = onDisposed {
	  disposable = Disposables.create(with: disposed)  
	} else {
	  disposable = Disposables.create()
	} 

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 注意到创建 observer 里的 event,可以看到在 .error 和 .completed 里,都调用 dispose 方法,也就是上面 AnonymousDisposable 里的 dispose 方法,在完成或者报错后,要销毁这个订阅关系:
	switch event {
	        case .next(let value):
	            onNext?(value)
	        case .error(let error):
	            if let onError = onError {
	                onError(error)
	            }
	            disposable.dispose()
	        case .completed:
	            onCompleted?()
	            disposable.dispose()
	        }
	    }

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 那么,.next 事件是如何调用 dispose 的呢?我们注意到这里创建了一个销毁者 Disposables,继续进入:
	return Disposables.create(
		self.asObservable().subscribe(observer),
		disposable
	)

  
 
  • 1
  • 2
  • 3
  • 4
  • 创建一个 BinaryDisposable 二元销毁者,把刚刚的两个要销毁的 disposable 都传进去,返回Disposables可以让外界随时随地的调用 dispose():
	// Creates a disposable with the given disposables.
	public static func create(_ disposable1: Disposable, _ disposable2: Disposable) -> Cancelable {
		return BinaryDisposable(disposable1, disposable2)
	}

  
 
  • 1
  • 2
  • 3
  • 4
  • 点进 BinaryDisposable,可以看到把传递进来的 disposable1 和 disposable2 都保存起来:
	private final class BinaryDisposable : DisposeBase, Cancelable {

    private let _isDisposed = AtomicInt(0)

    // state
    private var _disposable1: Disposable?
    private var _disposable2: Disposable?

    /// - returns: Was resource disposed.
    var isDisposed: Bool {
        return isFlagSet(self._isDisposed, 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()
    }
	func dispose() {
	        if fetchOr(self._isDisposed, 1) == 0 {
	            self._disposable1?.dispose()
	            self._disposable2?.dispose()
	            self._disposable1 = nil
	            self._disposable2 = nil
	        }
	    }
	}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 二元销毁者保存 2 个销毁者对象 _disposable1 和 _disposable2,dispose() 使用 fetchOr 保证销毁代码执行一次,分别调用 2 个销毁者的 dispose() 方法,并设置为 nil。self.asObservable().subscribe(observer) 方法的调用,我们知道订阅流程会来到 Producer 的 subscribe(observer)。这里也看到有一个 dispose() 方法:
	func dispose() {
	    if fetchOr(self._isDisposed, 1) == 0 {
	        self._disposable1?.dispose()
	        self._disposable2?.dispose()
	        self._disposable1 = nil
	        self._disposable2 = nil
	    }
	}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 那么,self.asObservable().subscribe(observer) 里创建的关键销毁者到底是什么呢?
	return Disposables.create(
		self.asObservable().subscribe(observer),
		disposable
	)

  
 
  • 1
  • 2
  • 3
  • 4
  • 直接找 Producer 里的 subscribe 方法(为什么直接找 Producer 呢?在 RxSwift 核心逻辑的时候,了解 Producer 里的 subscribe 是会先执行的,具体请参考:RxSwift之深入解析核心逻辑Observable的底层原理),可以看到 SinkDisposer(),如下所示:
	let disposer = SinkDisposer()
	let sinkAndSubscription = self.run(observer, cancel: disposer)
disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink, subscription: sinkAndSubscription.subscription)

  
 
  • 1
  • 2
  • 3
  • 首先看看 self.run 返回的是什么?可以发现,返回的是 AnonymousObservableSink 和 subscription 一个元组类型,subscription 是一个 AnonymousDisposable:
	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)
	    }

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 可能会不理解为什么是 AnonymousDisposable?因为 sink.run 就是调用的这里保存的 _subscribeHandler,而这个 _subscribeHandler 是由外界传递过来的闭包,就是 create 后面跟随的闭包:
	// 创建序列
	let ob = Observable<Any>.create { (observer) -> Disposable in
    observer.onNext("1111")
    return Disposables.create { print("销毁释放了")} // dispose.dispose()
        }

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 继续,那么 disposer.setSinkAndSubscription 干了什么事情呢?
	let disposer = SinkDisposer()
	let sinkAndSubscription = self.run(observer, cancel: disposer)
disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink, subscription: sinkAndSubscription.subscription)

  
 
  • 1
  • 2
  • 3
  • 这里把 sink 和 subscription 都保存起来了,还可以看到有一个 previousState 的状态,如果状态满足的话,就会调用销毁方法,把这两个都销毁。其实是可以理解为,就是在加入的对象其实需要销毁的,不应该保留的,那么没必要给它继续保留生命周期。
	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
        }
    }

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 普通的销毁者是 AnonymousDisposable,而这里使用的是 SinkDisposer:
    • 初始化 SinkDisposer 类型的 disposer;
    • sinkAndSubscription 是子类返回的元组 (sink: sink, subscription: subscription),
      sink 保存观察者 observer,销毁者 disposer,subscription 保存的是外界返回的销毁者;
    • disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink, subscription: sinkAndSubscription.subscription),disposer 保存 _sink 和 subscription previousState 状态判断对象是否已经销毁,如果已销毁则调用 sink 和 _subscription 的 dispose() 并设置为 nil;
    • SinkDisposer 的 func dispose() 通过 previousState 状态保证只销毁一次,
      sink 和 _subscription 分别调用 dispose() 并设置为 nil。
  • dispose() 方法在什么时候执行?
    • 完成和错误信号的响应式必然会直接开启销毁;
    • 手动调用 dispose.dispose();
    • 系统帮助销毁。
  private func dispose() {
        let oldDisposables = self._dispose()

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

    private func _dispose() -> [Disposable] {
        self._lock.lock(); defer { self._lock.unlock() }

        let disposables = self._disposables
        
        self._disposables.removeAll(keepingCapacity: false)
        self._isDisposed = true
        
        return disposables
    }
    
    deinit {
        self.dispose()
    }

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

四、销毁的本质

  • 通过分析,我们知道 RxSwift 的销毁者实际上销毁的是响应式关系。RxSwift 通过序列和观察者来建立响应关系,如果断开,响应关系就已达到销毁的目标。
  • 关于对象的回收,外界观察者和序列会随着它们的作用域空间而释放,内部创建的临时序列和观察者都会随着对外的观察者和序列的生命周期而销毁释放。

五、总结

  • Disposables.create(self.asObservable().subscribe(observer),disposable) 调用订阅时创建的 Disposables的dispose(),然后对二元销毁者分别调用 dispose() 并设置为 nil;
  • disposable 保存的是订阅时传入的闭包,disposable.dispose() 销毁 RxSwift 与外界的关联。self.asObservable().subscribe(observer) 是 SinkDisposer,因此调用的是 SinkDisposer.dispose();
  • SinkDisposer.dispose() 对保存的 2 个属性分别调用 dispose() 并设置为nil,subscription 保存的是外界创建序列时的闭包,因此 subscription.dispose() 也是切断RxSwift 与外界的关联,_sink.dispose() 调用保存的属性_cancel的dispose()。
  • RxSwift 为了统一性,会对保存的属性都调用一次 dispose(),如果有相互包含的属性,会有相互调用 dispose() 的情况。比如,SinkDisposer.dispose() 会调用 sink.dispose(),而执行 sink.dispose() 又将会执行 SinkDisposer.dispose()。

文章来源: blog.csdn.net,作者:Serendipity·y,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/Forever_wj/article/details/119705346

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。