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

results matching ""

    No results matching ""