RxSwift初窺

前言

很久一段時間沒寫博客了,一方面是自己各種事情折騰,二是新項目開始用Swift了,邊學邊做忙死了,現(xiàn)在終于快忙完了。由于接下來項目要使用RxSwift,所以研究一下RxSwift。

RxSwift概要

RxSwift是Swift函數(shù)響應式編程的一個開源庫,由Github的ReactiveX組織開發(fā),維護。目前在GitHub上有10000+star。
RxSwift的目的是讓讓數(shù)據(jù)/事件流和異步任務能夠更方便的序列化處理,能夠使用Swift進行響應式編程。

RxSwift中的基本概念

Observable

在ReactiveX中一個觀察者(Observer)訂閱一個被觀察的對象。這個觀察者對Observable發(fā)出的無論是單個對象或者是一串對象作出反饋。這種模式有利于并發(fā)操作因為它不需要阻塞線程,當?shù)却粋€Observable發(fā)送對象的過程中,它建立一種像哨兵一樣的機制,我們稱之為觀察者,他會一直關注那個Observable然后做出適當?shù)姆磻T赗eactiveX對Observable的說明中,有這么一張圖:

legend.png

在最上面的一排,就是一個Observable。從左到右,表示時間由遠到進的流動過程。上面的每一個形狀,就表示在某個時間點發(fā)生的事件,而最右邊的豎線則表示事件成功結束。

Operators

在RxSwift中,操作符operator也是一個很重要的概念,關于它的詳細介紹在ReactiveX官網(wǎng)可以看到。常用操作符分為兩大類,一類用于創(chuàng)建Observable;這些不同的方法可以針對不同的事件流生成Observable。另一類是接受Observable作為參數(shù),并返回意義新的Observable。

創(chuàng)建一個事件隊列

創(chuàng)建一個簡單的事件隊列很簡單,代碼如下:

_ = Observable.of(1,2,3,4,5,6,7,8,9)
_ = Observable.from([1,2,3,4,5,6,7,8,9])

上面這里我們就用了兩個operator來創(chuàng)建Observable:

  • of: 用固定數(shù)量的元素生成一個Observable;
  • from: 用一個Sequence類型的對象創(chuàng)建一個Observable;
    這兩個operator返回的結果是一樣的,都是一個包含1-9的Observable。

處理事件序列

在開發(fā)中,我們有時候因為各種需求需要對事件序列進行處理加工。例如我要把上面的事件序列變成一個字符串序列,用map操作符就可以做到。

_ = Observable.of(1,2,3,4,5,6,7,8,9).map({String($0)})

map是一個可以對Observable中的元素變形的operator,它返回一個新的Observable對象。
我們還可以篩選出符合條件的事件序列

_ = Observable.of(1,2,3,4,5,6,7,8,9).filter({$0 % 2 == 0})

上面filter篩選出一個只含有偶數(shù)的時間序列
看到filtermap感覺和集合中的filtermap方法非常類似,但它們執(zhí)行的邏輯卻截然不同。調用集合類型中的filtermap方法,表達的是同步執(zhí)行的概念,在調用方法的同事,結合就被立即加工處理了。但是我們創(chuàng)建的bservable,表達的是異步操作。Observable中的每一個元素,都可以理解為一個異步發(fā)生的時間。因此,當我們隊Observable調用filtermap方法時,只表示我們要對事件序列中的元素進行處理的邏輯,并不會立即對Observable中的元素進行處理。下面這個例子可以驗證:

_ = Observable.of(1,2,3,4,5,6,7,8,9)
    .filter({
        if $0 % 2 == 0 {
            print($0)
            return true
        }
        return false
    })

執(zhí)行這段代碼,在控制臺上并沒有打印任何消息。也就是說,我們沒有實際執(zhí)行任何的篩選邏輯。

訂閱事件

上面的刷選什么時候會被執(zhí)行呢?那就是有人訂閱這個事件的時候。

let numberObservable = Observable.of(1,2,3,4,5,6,7,8,9)
    .filter({
        if $0 % 2 == 0 {
            print($0)
            return true
        }
        return false
    })
    
numberObservable.subscribe { (event) in
    print("event: \(event)")
}

上面這段代碼的執(zhí)行結果如下:

2
event: next(2)
4
event: next(4)
6
event: next(6)
8
event: next(8)
event: completed

這說明當我們訂閱了這個事件序列,我們就能夠關注到篩選的過程和結果了。

subscribe也是一個operator

在上面的例子中,我們可以看到最后有一個event: completed,這就表示Observable事件流成功結束了。
實際上,subscribe也是一個operator,用于把事件的訂閱者(Observer)和事件的產生者(Observable)關聯(lián)起來。而Observable和Observer之間,有著以下的約定:

  • 當Observable正常發(fā)送事件時,會調用Observer提供的onNext方法,這個過程給你習慣上叫做emissions;
  • 當Observable成功結束時,回到用Observer提供的onCompleted方法;因此,在最后一次調用onNext之后,就會調用onCompleted;
  • 當Observable發(fā)生錯誤時,就會調用Observer提供的onError方法,并且,一旦發(fā)生錯誤,就不會再繼續(xù)發(fā)送其他時間了。對于調用onComplete和onNext的過程,習慣上叫做notifications;

在RxSwift里,還有一個約定,叫做onDisposed,指的是Observable使用的資源被回收的時候,會調用Observer提供的onDisposed方法。

Observable dispose

一般情況下,Observable分為兩種:

  • 在有限的時間內會自動結束(Completed/Error),比如一個網(wǎng)絡請求當做一個序列,當網(wǎng)絡請求完成的時候,Observable自動結束,資源會被釋放
  • 信號不會自己結束,最簡單的就是一個Timer,每隔一段時間就會發(fā)送一個新的信號過來,這時候就需要手動監(jiān)聽來釋放相應的資源。

手動監(jiān)聽釋放也分為兩種方法,分別是顯式釋放以及隱式釋放:

  • 顯式釋放 直接調用釋放方法進行資源的釋放,如下面的實例
public func delay(_ delay: Double,
                  closure: @escaping (Void) -> Void) {
    
    DispatchQueue.main.asyncAfter(
    deadline: .now() + delay) {
        closure()
    }
}

let disposable =
            Observable<Int>.interval(1, scheduler: MainScheduler.instance)
                .subscribe(
                    onNext: { print("Subscribed: \($0)") },
                    onDisposed: { print("The queue was disposed.") })
        
        delay(3) {
            disposable.dispose()
        }

執(zhí)行效果如下:

Subscribed: 0
Subscribed: 1
Subscribed: 2
The queue was disposed.

上面代碼創(chuàng)建一個輔助函數(shù)delay(),然后在delay()之后直接調用dispose()方法,這是顯式釋放

  • 隱式釋放 通過DisposeBag來進行,它類似于Objective-C中ARC的自動釋放池機制,當我們創(chuàng)建了某個實例后,會被添加到所在線程的自動釋放池中,而自動釋放池會在一個RunLoop周期后進行池子的釋放與重建;DisposeBag對于Rxswift就像自動釋放池一樣,我們把資源天機到DisposeBag中,讓資源隨著DIsposeBag一起釋放。如下實例:
var bag = DisposeBag()

Observable<Int>.interval(1, scheduler: MainScheduler.instance)
    .subscribe(
        onNext: { print("Subscribed: \($0)") },
        onDisposed: { print("The queue was disposed.") })
    .disposed(by: bag)

delay(3) {
    bag = DisposeBag()
}

這個執(zhí)行效果和上面的是一樣的,這就是隱式釋放。

小結

RxSwift之路還很長,需要不斷學習,不斷積累。

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

相關閱讀更多精彩內容

友情鏈接更多精彩內容