Observable dispose 的时机
https://beeth0ven.github.io/RxSwift-Chinese-Documentation/content/rxswift_core/disposable.html
Observable
发出了completed
或者error
事件之后会直接释放如果一直没
completed
或者error
, 调用dispose()
会提前dispose
如果一直没
completed
或者error
, 若调用disposed(by: disposeBag)
,disposeBag
释放时候Observable
才会dispose
测试代码:
class DisposableViewController: UIViewController {
let disposeBag = DisposeBag()
deinit {
print("Deinit:" + self.debugDescription)
}
override func viewDidLoad() {
super.viewDidLoad()
testDisposeTime()
}
// MARK: DisposeTime
func testDisposeTime() {
// observer.onCompleted()之后会直接dispose
// 如果一直没 onCompleted(), 调用dispose()才会dispose
// 如果一直没 onCompleted(), 调用disposed(by: disposeBag), disposeBag释放时候才会dispose
// Observable 1: 不发送 .onCompleted() 不调用 .dispose()
_ = Observable<String>
.create({ (observer) -> Disposable in
observer.onNext(
"""
\n
Observable 1: 不发送 .onCompleted() 不调用 .dispose()
\t\t\t 永远不会释放
"""
)
return Disposables.create {
print("Observable 1: Now Dispose")
}
})
.subscribe(onNext: { (s) in
print(s)
})
// Observable 2: 会发送 .onCompleted() 的 Observable
_ = Observable<String>
.create({ (observer) -> Disposable in
observer.onNext(
"""
\n
Observable 2: 会发送 .onCompleted() 的 Observable
\t\t\t 完成后就会释放
"""
)
observer.onCompleted()
return Disposables.create {
print("Observable 2: Now Dispose")
}
})
.subscribe(onNext: { (s) in
print(s)
})
// Observable 3: 不发送 .onCompleted() , 调用 .dispose()
Observable<String>
.create({ (observer) -> Disposable in
observer.onNext(
"""
\n
Observable 3: 不发送 .onCompleted() , 调用 .dispose()
\t\t\t 调用 .dispose() 时候释放
"""
)
return Disposables.create {
print("Observable 3: Now Dispose")
}
})
.subscribe(onNext: { (s) in
print(s)
})
.dispose()
// Observable 4: 不发送 .onCompleted() , 调用 .disposed(by: disposeBag)
Observable<String>
.create({ (observer) -> Disposable in
observer.onNext(
"""
\n
Observable 4: 不发送 .onCompleted() , 调用 .disposed(by: disposeBag)
\t\t\t disposeBag释放时候(VC deinit之后)释放
"""
)
return Disposables.create {
print("Observable 4: Now Dispose")
}
})
.subscribe(onNext: { (s) in
print(s)
})
.disposed(by: disposeBag)
}
}
输出如下:
Observable 1: 不发送 .onCompleted() 不调用 .dispose()
永远不会释放
Observable 2: 会发送 .onCompleted() 的 Observable
完成后就会释放
Observable 2: Now Dispose
Observable 3: 不发送 .onCompleted() , 调用 .dispose()
调用 .dispose() 时候释放
Observable 3: Now Dispose
Observable 4: 不发送 .onCompleted() , 调用 .disposed(by: disposeBag)
disposeBag释放时候(VC deinit之后)释放
Deinit:<RxSwiftExample.DisposableViewController: 0x7fa0a6e1d4e0>
Observable 4: Now Dispose
Disposable - 可被清除的资源
https://beeth0ven.github.io/RxSwift-Chinese-Documentation/content/rxswift_core/disposable.html
通常来说,一个序列如果发出了 error
或者 completed
事件,那么所有内部资源都会被释放。如果你需要提前释放这些资源或取消订阅的话,那么你可以对返回的 可被清除的资源(Disposable) 调用 dispose
方法。
调用 dispose
方法后,订阅将被取消,并且内部资源都会被释放。通常情况下,你是不需要手动调用 dispose
方法的,这里只是做个演示而已。我们推荐使用 清除包(DisposeBag) 或者 takeUntil 操作符 来管理订阅的生命周期。
func testDispose() {
for i in 1...4 {
Observable<String>
.create({ (observer) -> Disposable in
observer.onNext("Observable \(i) onNext")
return Disposables.create {
print("Observable \(i): Now Dispose")
}
})
.subscribe({ (e) in
print(e)
})
.dispose()
}
}
输出如下
next(Observable 1 onNext)
Observable 1: Now Dispose
next(Observable 2 onNext)
Observable 2: Now Dispose
next(Observable 3 onNext)
Observable 3: Now Dispose
next(Observable 4 onNext)
Observable 4: Now Dispose
DisposeBag - 清除包
因为我们用的是 Swift ,所以我们更习惯于使用 ARC 来管理内存。那么我们能不能用 ARC 来管理订阅的生命周期了。答案是肯定了,你可以用 清除包(DisposeBag) 来实现这种订阅管理机制。当 清除包(DisposeBag) 被释放的时候,清除包 内部所有 可被清除的资源(Disposable) 都将被清除。
func testDisposeBag() {
let funcDisposeBag = DisposeBag()
for i in 1...4 {
Observable<String>
.create({ (observer) -> Disposable in
observer.onNext("Observable \(i) onNext")
return Disposables.create {
print("Observable \(i) Now Dispose")
}
})
.subscribe({ (e) in
print(e)
})
.disposed(by: funcDisposeBag)
}
}
输出如下:
next(Observable 1 onNext)
next(Observable 2 onNext)
next(Observable 3 onNext)
next(Observable 4 onNext)
Observable 1 Now Dispose
Observable 2 Now Dispose
Observable 3 Now Dispose
Observable 4 Now Dispose
这个例子中 funcDisposeBag
在函数运行完之后释放,当函数运行结束时, funcDisposeBag
就被释放,那么这里的 4 次订阅也就被取消了。
takeUntil
另外一种实现自动取消订阅的方法就是使用 takeUntil
操作符,上面的演示代码也可以通过使用 takeUntil
来实现:
@IBAction func testTakeUntil() {
for i in 1...4 {
let observable = Observable<String>.create({ (observer) -> Disposable in
observer.onNext("Observable \(i) onNext")
return Disposables.create {
print("Observable \(i): Now Dispose")
}
})
_ = observable
.takeUntil(self.rx.deallocated)
.subscribe({ (e) in
print("Observable \(i): " + e.debugDescription)
})
}
}
这将使得订阅一直持续到控制器的 dealloc 事件产生为止。输出为:
Observable 1: next(Observable 1 onNext)
Observable 2: next(Observable 2 onNext)
Observable 3: next(Observable 3 onNext)
Observable 4: next(Observable 4 onNext)
Deinit:<RxSwiftExample.DisposableViewController: 0x7ff4d2c3a6c0>
Observable 1: completed
Observable 1: Now Dispose
Observable 2: completed
Observable 2: Now Dispose
Observable 3: completed
Observable 3: Now Dispose
Observable 4: completed
Observable 4: Now Dispose