可被清除的資源Disposable
是RxSwift
的核心成員之一,它主要是用來清除再也不須要的資源。那麼下面來探索一下RxSwift
是怎樣管理這些資源的生命週期呢。 api
error
或者 completed
事件,那麼全部內部資源都會被釋放,不須要咱們手動釋放。Disposable
) 調用 dispose
方法。DisposeBag
)來管理訂閱的生命週期,通常是把資源加入到一個全局的DisposeBag
裏面,它跟隨着頁面的生命週期,當頁面銷燬時DisposeBag
也會隨之銷燬,同時DisposeBag
裏面的資源也會被一一釋放。var disposeBag = DisposeBag() // 來自父類 ViewController
override func viewDidLoad() {
super.viewDidLoad()
...
usernameValid
.bind(to: passwordOutlet.rx.isEnabled)
.disposed(by: disposeBag)
usernameValid
.bind(to: usernameValidOutlet.rx.isHidden)
.disposed(by: disposeBag)
}
複製代碼
下面這一段代碼是常規的建立一個序列,而後訂閱,最後手動銷燬的流程。安全
let observable = Observable<Any>.create { (observer) -> Disposable in
observer.onNext("七夕快樂")
return Disposables.create {
print("銷燬釋放了")
}
}
let dispose = observable.subscribe(onNext: { (message) in
print("有一條新消息:\(message)")
}, onError: { (error) in
print("錯誤")
}, onCompleted: {
print("完成")
}) {
print("銷燬回調")
}
print("開始調用dispose")
dispose.dispose()
複製代碼
執行結果:
有一條新消息:七夕快樂
開始調用dispose
銷燬釋放了
銷燬回調
複製代碼
Observable<Any>.create
方法有一個尾隨閉包,須要返回一個實現了Disposable
協議的實例。Disposables.create
方法裏面看看extension Disposables {
public static func create(with dispose: @escaping () -> Void) -> Cancelable {
return AnonymousDisposable(disposeAction: dispose)
}
}
複製代碼
AnonymousDisposable
對象並返回,很明顯,這是一個匿名銷燬者,跟建立序列的時候會建立一個匿名序列實現方式很是類似。fileprivate final class AnonymousDisposable : DisposeBase, Cancelable {
public typealias DisposeAction = () -> Void
private let _isDisposed = AtomicInt(0)
private var _disposeAction: DisposeAction?
public var isDisposed: Bool {
return isFlagSet(self._isDisposed, 1)
}
fileprivate init(_ disposeAction: @escaping DisposeAction) {
self._disposeAction = disposeAction
super.init()
}
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) == 0
這行代碼是控制if語句裏面只會進去一次。fetchOr
方法的具體實現:AtomicInt
是繼承NSLock
,在更改value
值的時候加了一把鎖,保證線程安全,而後運用了或運算並保存結果。位運算更加的高效。self._disposeAction
賦值給臨時變量action
,而後置空self._disposeAction
,再執行action()
。這樣操做的緣由是若是_disposeAction
閉包是一個耗時操做,也可以保證_disposeAction
可以當即釋放。func fetchOr(_ this: AtomicInt, _ mask: Int32) -> Int32 {
this.lock()
let oldValue = this.value
this.value |= mask
this.unlock()
return oldValue
}
複製代碼
final class AtomicInt: NSLock {
fileprivate var value: Int32
public init(_ value: Int32 = 0) {
self.value = value
}
}
複製代碼
_subscriberHandle
裏面,其實這個流程以前還有一個很是重要的流程:訂閱,進入到observable.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()
}
let observer = AnonymousObserver<Element> { event in
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
)
}
複製代碼
Disposable
對象,並保存了銷燬回調閉包,當執行銷燬時,會把消息回調出去disposable.dispose()
,這就證明了前面說的:一個序列若是發出了 error
或者 completed
事件,那麼全部內部資源都會被釋放,不須要咱們手動釋放。return Disposables.create( self.asObservable().subscribe(observer), disposable )
,這裏返回的Disposable
對象就是咱們外面手動調用dispose.dispose()
方法的dispose
對象,或者說是加入到全局的DisposeBag
的銷燬者。public static func create(_ disposable1: Disposable, _ disposable2: Disposable) -> Cancelable {
return BinaryDisposable(disposable1, disposable2)
}
複製代碼
func dispose() {
if fetchOr(self._isDisposed, 1) == 0 {
self._disposable1?.dispose()
self._disposable2?.dispose()
self._disposable1 = nil
self._disposable2 = nil
}
}
複製代碼
dispose()
時會把2個銷燬者分別銷燬self.asObservable().subscribe(observer)
的返回值是什麼。來到Producer
類的subscribe
方法let disposer = SinkDisposer()
let sinkAndSubscription = self.run(observer, cancel: disposer)
disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink, subscription: sinkAndSubscription.subscription)
return disposer
複製代碼
SinkDisposer
對象並返回,因此前面建立二元銷燬者的第二個參數就是它。通過以前對RxSwift
核心邏輯的分析文章,咱們知道sink是鏈接序列和觀察者的橋樑,當sink銷燬後,序列和觀察者之間就沒法通信了。self.run(observer, cancel: disposer)
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)
}
複製代碼
AnonymousObservableSink
對象,並保存了上一步建立的SinkDisposer
對象。在AnonymousObservableSink
的源碼裏面發現on
方法中,當發出完成和錯誤信號後,會當即執行dispose
進行銷燬,因此一旦咱們的序列發出完成或者錯誤信號後就沒法再次響應了!sink.run(self)
,方法裏面執行的是parent._subscribeHandler(AnyObserver(self))
,_subscribeHandler
閉包就是外面建立序列Observable<Any>.create
的尾隨閉包,因此返回值就是Disposables.create {print("銷燬釋放了")}
。setSinkAndSubscription
方法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
和 subscription
,就是上一步返回的銷燬者和AnonymousObservableSink
對象,AnonymousObservableSink
裏面保存了sink的銷燬者SinkDisposer
dispose()
而後置空 nil
dispose.dispose()
銷燬時銷燬的究竟是什麼呢func dispose() {
let previousState = fetchOr(self._state, DisposeState.disposed.rawValue)
if (previousState & DisposeState.disposed.rawValue) != 0 {
return
}
if (previousState & DisposeState.sinkAndSubscriptionSet.rawValue) != 0 {
sink.dispose()
subscription.dispose()
self._sink = nil
self._subscription = nil
}
}
複製代碼
dispose()
,咱們查看 dispose()
得出: 就是把初始化的時候保存的兩個屬性進行銷燬而後置空。RxSwift
中,sink
存放了序列和觀察者,來創建它們之間的響應關係,當把序列和觀察者之間的橋樑sink
銷燬了,也就斷開了它們之間的響應關係,從而沒法再接收到消息。error
或者 completed
事件,那麼全部內部資源都會被釋放,不須要咱們手動釋放。disposeBag
,是在disposeBag
對象銷燬時,依次銷燬裏面存儲的東西