就問此時(shí)此刻還有誰芹枷?45度仰望天空,該死莲趣!我這無處安放的魅力鸳慈!
- RxSwift(1)—— 初探
- RxSwift(2)—— 核心邏輯源碼分析
- RxSwift(3)—— Observable序列的創(chuàng)建方式
- RxSwift(4)—— 高階函數(shù)(上)
- RxSwift(5)—— 高階函數(shù)(下)
- RxSwift(6)—— scheduler源碼解析(上)
- RxSwift(7)—— scheduler源碼解析(下)
- RxSwift(8)—— KVO底層探索(上)
- RxSwift(9)—— KVO底層探索(下)
- RxSwift(10)—— 場(chǎng)景序列總結(jié)
- RxSwift(11)—— 銷毀者-dispose源碼解析
- RxSwift(12)—— Subject即攻也守
- RxSwift(13)—— 爬過的坑
- RxSwift(14)—— MVVM雙向綁定
RxSwift目錄直通車--- 和諧學(xué)習(xí),不急不躁喧伞!
在這個(gè)篇章我們分析RxSwift一個(gè)非常重要的元素 一 銷毀者走芋!這一元素也是我們
Rxswift
四俊杰之一。銷毀者在Rxswift
的世界里面扮演的角色也是非常重要的潘鲫,所以對(duì)它的深入解析翁逞,才能幫助我們對(duì)Rxswift
更好的理解
銷毀者初探
首先給大家看一段代碼,我們從基本序列創(chuàng)建和訂閱開始分析
// 創(chuàng)建序列
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("銷毀回調(diào)")
}
- 這段代碼里面關(guān)于銷毀者相關(guān)的就是我們創(chuàng)建序列的回調(diào)閉包
Disposables.create {print("銷毀釋放了")}
按照前面我給大家分享的代碼技巧溉仑,這里就不會(huì)迷路挖函!可以直接定位到核心代碼
extension Disposables {
public static func create(with dispose:) -> Cancelable {
return AnonymousDisposable(disposeAction: dispose)
}
}
- 創(chuàng)建了一個(gè)匿名銷毀者
AnonymousDisposable
跟我們的序列,訂閱者一樣的手法浊竟,不同的業(yè)務(wù)邏輯必然還有其他細(xì)節(jié)操作怨喘,但是我們從一般入手快速直接
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()
}
}
}
- 上面我們可以看到初始化就是保存了響應(yīng)回調(diào)閉包,那么在什么時(shí)候回調(diào)呢振定?就在下面我們標(biāo)記的核心邏輯代碼 -
dispose()
-
fetchOr(self._isDisposed, 1)
是一個(gè)單項(xiàng)標(biāo)記手段必怜,我們一般操作就是屬性標(biāo)記,這里利用的是更裝逼的算法標(biāo)記:降低依賴和更加快速 - 上面方法的意思就是保證只會(huì)銷毀一次
- 下面就是對(duì)回調(diào)閉包取出然后置空銷毀
self._disposeAction = nil
- 對(duì)取出的閉包調(diào)用執(zhí)行:
action()
現(xiàn)在感覺一切很順利后频,但是聰明的我們一定要知道這里落下一個(gè)重要的前導(dǎo)因素:什么時(shí)候調(diào)用了 dispose()
銷毀調(diào)用
上面的流程梳庆,我們是在序列的回調(diào)閉包:subscriberHandle
里面,其實(shí)這個(gè)流程之前還有一個(gè)非常重要的流程:訂閱 subscriber
if let disposed = onDisposed {
disposable = Disposables.create(with: disposed)
}else {
disposable = Disposables.create()
}
- 這里就是保存外界銷毀閉包的保存 - 達(dá)到提示銷毀
switch event {
case .next(let value):
onNext?(value)
case .error(let error):
// 響應(yīng)外界調(diào)回閉包
disposable.dispose()
case .completed:
// 響應(yīng)外界調(diào)回閉包
disposable.dispose()
}
- 觀察者回調(diào)里面調(diào)用, 響應(yīng)外界調(diào)回閉包
-
return Disposables.create(self.asObservable().subscribe(observer),disposable)
綜合來看靠益,我們的重點(diǎn)必然在這句代碼丧肴,溝通下面流程的subscribe
, 外界訂閱返回的銷毀者(可以隨時(shí)隨地進(jìn)行dispose.dispose()
) - 上面代碼跟進(jìn)去看到
BinaryDisposable(disposable1, disposable2)
原來創(chuàng)建的二元銷毀者!
func dispose() {
if fetchOr(self._isDisposed, 1) == 0 {
self._disposable1?.dispose()
self._disposable2?.dispose()
self._disposable1 = nil
self._disposable2 = nil
}
}
- 二元銷毀者的
dispose
方法也在預(yù)料之中胧后,分別銷毀 - 那么我們的重點(diǎn)就應(yīng)該探索芋浮,在
subscribe
這里面創(chuàng)建的關(guān)鍵銷毀者是什么? - 下面我們進(jìn)入非常熟悉的:
Producer
let disposer = SinkDisposer()
let sinkAndSubscription = self.run(observer, cancel: disposer)
disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink,
subscription: sinkAndSubscription.subscription)
// 返回銷毀者
return disposer
- 看到
SinkDisposer
我心里舒服了壳快!一切都是那么熟悉,普通銷毀者:AnonymousDisposable
, 關(guān)鍵銷毀者:SinkDisposer
- 首先我們不著急具體去查閱
SinkDisposer
里面實(shí)現(xiàn) - 先看什么東西進(jìn)入了
SinkDisposer
-
self.run(observer, cancel: disposer)
證明里面需要用到SinkDisposer
-
disposer.setSinkAndSubscription
常規(guī)操作,也看看源碼把
func setSinkAndSubscription(sink: Disposable, subscription: Disposable) {
self._sink = sink
self._subscription = subscription
// 獲取狀態(tài)
let previousState = fetchOr(self._state,
DisposeState.sinkAndSubscriptionSet.rawValue)
// 如果狀態(tài)滿足就銷毀
if (previousState & DisposeState.disposed.rawValue) != 0 {
sink.dispose()
subscription.dispose()
self._sink = nil
self._subscription = nil
}
}
- 保存了兩個(gè)屬性 :
sink
和subscription
(就是外界創(chuàng)建序列的閉包的返回銷毀者) - 取了某一個(gè)狀態(tài):
previousState
,判斷狀態(tài)的條件七婴,然后執(zhí)行 這兩個(gè)保存屬性的銷毀和置空釋放銷毀 :.dispose() + = nil
- 其實(shí)是可以理解修肠,就是我們?cè)诩尤氲臇|西其實(shí)需要銷毀的嵌施,不應(yīng)該保留的吗伤,那么沒必要給它繼續(xù)保留生命跡象
OK 剩下我們還去一個(gè)傳進(jìn)去的銷毀者,去干嗎?我們也跟一下源碼!
// 創(chuàng)建 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)
// 關(guān)鍵點(diǎn):完成和錯(cuò)誤信號(hào)的響應(yīng)式必然會(huì)直接開啟銷毀的
self.dispose()
}
}
}
- 完成和錯(cuò)誤信號(hào)的響應(yīng)式必然會(huì)直接開啟銷毀的 :
self.dispose()
! 這里也解釋了:一旦我們的序列發(fā)出完成或者錯(cuò)誤就無法再次響應(yīng)了区丑! - 剩下一個(gè)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
}
}
- 無論我們直接銷毀還是系統(tǒng)幫助我們銷毀必然會(huì)調(diào)用:
dispose()
- 我們查看
dispose()
得出: 就是在初始化初期我們保留的兩個(gè)屬性的操作 -
sink.dispose() + self._sink = nil
&subscription.dispose() + self._subscription = nil
執(zhí)行相關(guān)釋放和銷毀 - 如果你細(xì)細(xì)品來你會(huì)慢慢感知到:這種設(shè)計(jì)是對(duì)的!
- 我們?cè)?
RxSwift
的世界里最重要的東西啥纸,我們就是通過:序列,觀察者 來建立響應(yīng)關(guān)系!如果我們斷開了響應(yīng)關(guān)系不就達(dá)到銷毀的目標(biāo)穗酥?然而我們斷開響應(yīng)關(guān)系最重要的就是:Sink
- 很多同學(xué)可能會(huì)問:那么我們創(chuàng)建的序列节吮、觀察者對(duì)象怎么辦透绩?你不管了碳竟?
- 第一:內(nèi)部創(chuàng)建的臨時(shí)序列和觀察者都會(huì)隨著對(duì)外的觀察者和序列的生命周期而銷毀釋放。
- 第二:外界觀察者和序列會(huì)隨著他們的作用域空間而釋放
- 第三:釋放不了只是對(duì)象的釋放有問題仙蚜,常規(guī)內(nèi)存管理問題
- 第四:最為一個(gè)再牛逼的框架也不能對(duì)程序員寫的代碼直接管理控制
- 第五:
RxSwift
的觀察和序列以及銷毀者就是普通對(duì)象娶桦,ARC
申請(qǐng)開辟內(nèi)存栗涂,開發(fā)人員正常處理就OK
RxSwift
的銷毀者的設(shè)計(jì)個(gè)人感覺還是比較精妙的菩混,對(duì)于整個(gè)框架的連貫和整體性再次驗(yàn)證疚脐!希望讀者讀者用心感受設(shè)計(jì)思路疟游!就問此時(shí)此刻還有誰颁虐?45度仰望天空役耕,該死!我這無處安放的魅力聪廉!