RxSwift - Observable 閱讀筆記

什么是 Observable

在 RxSwift 中,所有的事件都是基于隊(duì)列 (sequence) 的,Observable 會不斷在這條隊(duì)列上發(fā)送數(shù)據(jù) / 數(shù)據(jù)序列。而我們通過訂閱 Observable ,當(dāng)有事件被發(fā)送,就可以接受到事件通知。

Observable

Observable 生命周期

Observable 會發(fā)送三種事件類型,發(fā)送包含事件 element 的 next 事件,發(fā)送 completed 事件,作為事件序列的完結(jié)。

Completed

當(dāng)有錯誤發(fā)生時,Observable 會發(fā)送包含錯誤信息的 error(Error) 事件。

Error

Observable 可以一直發(fā)送 next 事件,直到發(fā)送了 error 或者 completed 事件,這條事件序列才會被終止。

Observable 的創(chuàng)建

RxSwift 提供了一系列創(chuàng)建 Observable 的方法

  • just

    創(chuàng)建一個只包含一個事件的序列。

    Observable<Int>.just(1)
    
  • of

    創(chuàng)建一個事件序列,包含參數(shù)中傳遞的事件

    Observable.of(1, 2, 3)
    
  • from

    通過 sequence 創(chuàng)建事件序列。

    Observable.from([1, 2, 3])
    
  • never

    創(chuàng)建一個不會傳遞任何事件也不會終止的序列

     Observable<Void>.never()
    
  • empty

    創(chuàng)建一個只發(fā)送 completed 事件的序列

    Observable<String>.empty()
    
  • error

    創(chuàng)建一個只發(fā)送 error 事件的序列

    Observable<String>.error(MyError.error)
    
  • range

    創(chuàng)建一個在某個范圍內(nèi)的 int 值的序列

    Observable<Int>.range(start: 1, count: 10)
    

訂閱 Observable

RxSwift 使用 subscribe() 來訂閱 Observable。這里需要強(qiáng)調(diào)的是,任何 Observable 只有在有訂閱者時才會發(fā)送事件,因此,例如上文提及的 Observable.of(1, 2, 3) 其實(shí)沒有發(fā)送任何事件。只有當(dāng)通過 subscribe() 訂閱時,Observable 才會發(fā)送事件

Observable<Int>
    .of(1, 2, 3)
    .subscribe({ event in
        print(event)
    })

打開控制臺,就會得到下面的打印結(jié)果

next(1)
next(2)
next(3)
completed

定義的 Observable 對象為每個元素發(fā)送了 .next 事件。最后發(fā)送了 .completed 事件,作為事件序列的結(jié)束。

.next 事件的元素是一個 Optional ,因此當(dāng)需要直接訪問這個值時,需要做解包操作

不過 RxSwift 提供了另一種訂閱函數(shù)來滿足訂閱要求。

Observable<Int>
    .of(1, 2, 3)
    .subscribe(onNext: { (element) in
        print(element)
    }, onError: { (error) in
        print(error)
    }, onCompleted: {
        print("Completed")
    }, onDisposed: {
        print("Disposed")
    })

Observable 處理與終止

當(dāng) Observable 有訂閱者時,才會開始不斷發(fā)送 .next 事件,直到發(fā)送一個 .error 或者 .completed 事件,事件序列結(jié)束

我們可以手動的通過取消訂閱來終止這個事件序列。

  • 單獨(dú)的為每一個 Observable 添加取消訂閱操作

    Observable
        .of(1, 2, 3)
        .subscribe(onNext: { (element) in
            print(element)
        }, onCompleted: {
            print("completed")
        }, onDisposed: {
            print("Disposed")
        })
        .dispose()
    

    控制臺的打印結(jié)果變成了

    1
    2
    3
    completed
    Disposed
    

    在調(diào)用了 dispose() 方法之后,當(dāng)前的 Observable 對象就停止向訂閱者發(fā)送消息了。

  • 統(tǒng)一管理 Observable 的釋放

    為每一個 Observable 都添加 dispose() 方法不僅顯得多余,并且如果在多個地方使用到這個 Observable 對象,在某處提前釋放了,可能會導(dǎo)致一些意想不到的問題。RxSwift 提供了一個 DisposeBag 來統(tǒng)一管理 Observable 的釋放問題

    let bag = DisposeBag()
    Observable
        .of(1, 2, 3)
        .subscribe(onNext: { (element) in
            print(element)
        })
        .addDisposableTo(bag)
    

    首先定義一個 DisposeBag 對象,之后就像使用 dispose() 一樣,在訂閱之后使用 addDisposableTo(_ bag: RxSwift.DisposeBag)Observable 添加到定義的 DisposeBag 對象中。

    DisposeBag 將是后面經(jīng)常使用到的處理 Observable 回收的方法。

自定義事件

循規(guī)蹈矩的 Observable 的創(chuàng)建方式,或多或少都無法滿足日常 PM 的需求。所以如何創(chuàng)建包含自定義事件的數(shù)據(jù)流呢?RxSwift 提供了兩種方式

  • create

    let disposeBag = DisposeBag()
    enum MyError: Error {
        case anError
    }
    Observable<String>
        .create({ (observer) in
            observer.onNext("1")
            observer.onError(MyError.anError)
            observer.onCompleted()
            observer.onNext("where is it?")
            return Disposables.create()
        })
    

    create 函數(shù)定義

    public static func create(_ subscribe: @escaping (RxSwift.AnyObserver<RxSwift.Observable.E>) -> Disposable) -> RxSwift.Observable<RxSwift.Observable.E>

    在傳遞的閉包內(nèi)部,我們可以自定義事件,對上述的 Observable 訂閱,我們將接收到下列事件

    1
    anError
    Disposed
    

    在接收到 .error 事件之后,整個事件序列就被終止了。

  • deferred 創(chuàng)建一個生成不同的事件序列的工廠方法

    試想這樣的使用場景,對于同一個 Observable,我們希望不同的訂閱者能訂閱到不同的數(shù)據(jù)流。

    let disposeBag = DisposeBag()
    var flip = false
    let factory: Observable<Int> = Observable.deferred({
        flip = !flip
        
        if flip {
            return Observable.of(1, 2, 3)
        } else {
            return Observable.of(4, 5, 6)
        }
    })
    for _ in 0 ... 3 {
        factory.subscribe(onNext: {
            print($0, terminator: "")
        })
        .disposed(by: disposeBag)
        print()
    }
    

    每個訂閱 factory 的訂閱者,都能獲得不同的事件序列,控制臺的打印結(jié)果為

    123
    456
    123
    456
    
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 RxSwift入坑解讀-你所需要知道的各種概念 沸沸騰關(guān)注 2016.11.27 19:11*字...
    楓葉1234閱讀 2,937評論 0 2
  • 最近在學(xué)習(xí)RxSwift相關(guān)的內(nèi)容,在這里記錄一些基本的知識點(diǎn),以便今后查閱。 Observable 在RxSwi...
    L_Zephyr閱讀 1,897評論 1 4
  • 本文章內(nèi)部分圖片資源來自RayWenderlich.com 本文結(jié)合自己的理解來總結(jié)介紹一下RxSwift最基本的...
    FKSky閱讀 3,044評論 4 14
  • 如果你要補(bǔ)鈣,還是應(yīng)該通過吃其他富含鈣質(zhì)的食物,比如說牛奶來補(bǔ)。而不要想通過喝骨頭湯來補(bǔ)。因?yàn)椋?、骨頭里含有很多...
    做個懂科學(xué)的憨人閱讀 393評論 0 2
  • 萌貓“胖花”的主人Yixi有事回國一個月,走之前把寵貓托付給了我。我和Alex (以下稱輕松熊)早就滿懷期待,代管...
    Shou撕鬼子閱讀 594評論 0 3

友情鏈接更多精彩內(nèi)容