RxSwift(11)— dispose源碼解析

就問此時此刻還有誰?45度仰望天空,該死!我這無處安放的魅力!程序員


RxSwift 目錄直通車 --- 和諧學習,不急不躁!算法


在這個篇章咱們分析RxSwift一個很是重要的元素 一 銷燬者!這一元素也是咱們 Rxswift 四俊傑之一。銷燬者Rxswift的世界裏面扮演的角色也是很是重要的,因此對它的深刻解析,才能幫助咱們對Rxswift更好的理解swift

銷燬者初探

首先給你們看一段代碼,咱們從基本序列建立和訂閱開始分析api

// 建立序列
let ob = Observable<Any>.create { (observer) -> Disposable in
    observer.onNext("Cooci")
    return Disposables.create {
            print("銷燬釋放了")
        }
}
// 序列訂閱
let dispose = ob.subscribe(onNext: { (anything) in
    print("訂閱到了:\(anything)")
}, onError: { (error) in
    print("訂閱到了:\(error)")
}, onCompleted: {
    print("完成了")
}) {
    print("銷燬回調")
}
複製代碼
  • 這段代碼裏面關於銷燬者相關的就是咱們建立序列的回調閉包 Disposables.create {print("銷燬釋放了")} 按照前面我給你們分享的代碼技巧,這裏就不會迷路!能夠直接定位到核心代碼
extension Disposables {
    public static func create(with dispose:) -> Cancelable {
        return AnonymousDisposable(disposeAction: dispose)
    }
}
複製代碼
  • 建立了一個匿名銷燬者 AnonymousDisposable 跟咱們的序列,訂閱者同樣的手法,不一樣的業務邏輯必然還有其餘細節操做,可是咱們從通常入手快速直接
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()
        }
    }
}
複製代碼
  • 上面咱們能夠看到初始化就是保存了響應回調閉包,那麼在何時回調呢?就在下面咱們標記的核心邏輯代碼 - dispose()
  • fetchOr(self._isDisposed, 1) 是一個單項標記手段,咱們通常操做就是屬性標記,這裏利用的是更裝逼的算法標記:下降依賴和更加快速
  • 上面方法的意思就是保證只會銷燬一次
  • 下面就是對回調閉包取出而後置空銷燬 self._disposeAction = nil
  • 對取出的閉包調用執行: action()

如今感受一切很順利,可是聰明的咱們必定要知道這裏落下一個重要的前導因素:何時調用了 dispose()閉包

銷燬調用

上面的流程,咱們是在序列的回調閉包:subscriberHandle裏面,其實這個流程以前還有一個很是重要的流程:訂閱 subscriber框架

if let disposed = onDisposed {
  disposable = Disposables.create(with: disposed)  
}else {
  disposable = Disposables.create()
 }
複製代碼
  • 這裏就是保存外界銷燬閉包的保存 - 達到提示銷燬
switch event {
case .next(let value):
    onNext?(value)
case .error(let error):
  // 響應外界調回閉包
    disposable.dispose()
case .completed:
  // 響應外界調回閉包
    disposable.dispose()
}
複製代碼
  • 觀察者回調裏面調用, 響應外界調回閉包
  • return Disposables.create(self.asObservable().subscribe(observer),disposable) 綜合來看,咱們的重點必然在這句代碼,溝通下面流程的 subscribe, 外界訂閱返回的銷燬者(能夠隨時隨地進行 dispose.dispose()
  • 上面代碼跟進去看到BinaryDisposable(disposable1, disposable2) 原來建立的二元銷燬者!
func dispose() {
    if fetchOr(self._isDisposed, 1) == 0 {
        self._disposable1?.dispose()
        self._disposable2?.dispose()
        self._disposable1 = nil
        self._disposable2 = nil
    }
}
複製代碼
  • 二元銷燬者的 dispose 方法也在預料之中,分別銷燬
  • 那麼咱們的重點就應該探索,在 subscribe 這裏面建立的關鍵銷燬者是什麼?
  • 下面咱們進入很是熟悉的:Producer
let disposer = SinkDisposer()
let sinkAndSubscription = self.run(observer, cancel: disposer)
disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink,
 subscription: sinkAndSubscription.subscription)
// 返回銷燬者
return disposer
複製代碼
  • 看到 SinkDisposer 我內心舒服了!一切都是那麼熟悉,普通銷燬者:AnonymousDisposable , 關鍵銷燬者: SinkDisposer
  • 首先咱們不着急具體去查閱 SinkDisposer 裏面實現
  • 先看什麼東西進入了 SinkDisposer
  • self.run(observer, cancel: disposer) 證實裏面須要用到 SinkDisposer
  • disposer.setSinkAndSubscription 常規操做,也看看源碼把
func setSinkAndSubscription(sink: Disposable, subscription: Disposable) {
    self._sink = sink
    self._subscription = subscription

// 獲取狀態 
    let previousState = fetchOr(self._state, 
DisposeState.sinkAndSubscriptionSet.rawValue)

// 若是狀態知足就銷燬
    if (previousState & DisposeState.disposed.rawValue) != 0 {
        sink.dispose()
        subscription.dispose()
        self._sink = nil
        self._subscription = nil
    }
}
複製代碼
  • 保存了兩個屬性 : sinksubscription(就是外界建立序列的閉包的返回銷燬者)
  • 取了某一個狀態:previousState,判斷狀態的條件,而後執行 這兩個保存屬性的銷燬和置空釋放銷燬 : .dispose() + = nil
  • 實際上是能夠理解,就是咱們在加入的東西其實須要銷燬的,不該該保留的,那麼不必給它繼續保留生命跡象

OK 剩下咱們還去一個傳進去的銷燬者,去幹嘛?咱們也跟一下源碼!函數

// 建立 sink 保存了銷燬者
let sink = AnonymousObservableSink(observer: observer, cancel: cancel)

// 中間流程省略。。。。

func on(_ event: Event<Element>) {
    switch event {
    case .next:
        self.forwardOn(event)
    case .error, .completed:
        if fetchOr(self._isStopped, 1) == 0 {
            self.forwardOn(event)
            // 關鍵點:完成和錯誤信號的響應式必然會直接開啓銷燬的
            self.dispose()
        }
    }
}
複製代碼
  • 完成和錯誤信號的響應式必然會直接開啓銷燬的 : self.dispose()! 這裏也解釋了:一旦咱們的序列發出完成或者錯誤就沒法再次響應了!
  • 剩下一個BIG問題: 到底咱們的銷燬的是什麼
func dispose() {
    let previousState = fetchOr(self._state, DisposeState.disposed.rawValue)

    if (previousState & DisposeState.sinkAndSubscriptionSet.rawValue) != 0 {
        sink.dispose()
        subscription.dispose()

        self._sink = nil
        self._subscription = nil
    }
}
複製代碼
  • 不管咱們直接銷燬仍是系統幫助咱們銷燬必然會調用:dispose()
  • 咱們查看 dispose() 得出: 就是在初始化初期咱們保留的兩個屬性的操做
  • sink.dispose() + self._sink = nil & subscription.dispose() + self._subscription = nil 執行相關釋放和銷燬
  • 若是你細細品來你會慢慢感知到:這種設計是對的!
  • 咱們在 RxSwift 的世界裏最重要的東西,咱們就是經過:序列,觀察者 來創建響應關係!若是咱們斷開了響應關係不就達到銷燬的目標?然而咱們斷開響應關係最重要的就是:Sink
  • 不少同窗可能會問:那麼咱們建立的序列、觀察者對象怎麼辦?你無論了?
  • 第一:內部建立的臨時序列和觀察者都會隨着對外的觀察者和序列的生命週期而銷燬釋放。
  • 第二:外界觀察者和序列會隨着他們的做用域空間而釋放
  • 第三:釋放不了只是對象的釋放有問題,常規內存管理問題
  • 第四:最爲一個再牛逼的框架也不能對程序員寫的代碼直接管理控制
  • 第五:RxSwift 的觀察和序列以及銷燬者就是普通對象,最爲開發人員正常處理就OK

RxSwift 的銷燬者的設計我的感受仍是比較精妙的,對於整個框架的連貫和總體性再次驗證!但願讀者讀者用心感覺設計思路!源碼分析

完美!解析到這裏,整個流程解析完畢post

就問此時此刻還有誰?45度仰望天空,該死!我這無處安放的魅力!學習

相關文章
相關標籤/搜索