一、RXSwift 介紹
1.1 什么是RX
- Rx 是 ReactiveX 的縮寫,簡(jiǎn)單來(lái)說(shuō)就是基于異步 Event(事件)序列的響應(yīng)式編程。
- Rx 可以簡(jiǎn)化異步編程方法,并提供更優(yōu)雅的數(shù)據(jù)綁定。讓我們可以時(shí)刻響應(yīng)新的數(shù)據(jù)同時(shí)順序地處理它們。
1.2 Rx 庫(kù)
- Rx 本身可以說(shuō)是一種跨平臺(tái)的標(biāo)準(zhǔn),它有自己的社區(qū)論壇,不管是 web 還是移動(dòng)開發(fā),都能用 Rx 的思維和方法來(lái)完成你的工作。
- 作為一種跨平臺(tái)標(biāo)準(zhǔn),目前已經(jīng)有許多基于不同開發(fā)語(yǔ)言的 Rx 的庫(kù)。除了我后面會(huì)著重介紹的 RxSwift 之外,還有 RxJava, RxJS, RxKotlin, Rx.NET...等等。
- 這些 Rx 庫(kù)雖然用的語(yǔ)言不同,但它們之間其實(shí)都是相通的,都有相同的 API。所以說(shuō)如果以后你使用別的語(yǔ)言做其他的方面的開發(fā),同樣是可以使用相同的思維甚至相同的方法接口(除了語(yǔ)言不同)來(lái)編程。
- 它的主頁(yè):http://reactivex.io
1.3 為什么要使用Rx
- 復(fù)合 - Rx 就是復(fù)合的代名詞
- 復(fù)用 - 因?yàn)樗讖?fù)合
- 清晰 - 因?yàn)槁暶鞫际遣豢勺兏?/li>
- 易用 - 因?yàn)樗橄蟮牧水惒骄幊?,使我們統(tǒng)一了代碼風(fēng)格
- 穩(wěn)定 - 因?yàn)?Rx 是完全通過單元測(cè)試的
二、RxSwift 介紹
2.1 RxSwift 的作用
- 在編寫代碼時(shí)我們經(jīng)常會(huì)需要檢測(cè)某些值的變化(比如:textFiled 輸入值的變化、數(shù)據(jù)請(qǐng)求完成或失敗的變化),然后進(jìn)行相應(yīng)的處理。
- 過去針對(duì)不同的情況,我們需要采用不同的事件傳遞方法去處理,比如:delegate、notification、target-action、KVO 等等。
- 而 RectiveX 機(jī)制(由 RxSwift 實(shí)現(xiàn))的出現(xiàn),讓程序里的事件傳遞響應(yīng)方法做到統(tǒng)一。將之前那些常用的事件傳遞方法(比如:delegate、notification、target-action 等等),全部替換成 Rx 的“信號(hào)鏈”方式。
2.2 如果我們平時(shí)使用的是 MVVM 開發(fā)模式的話,通過 RxSwift 可以獲得更加方便的數(shù)據(jù)綁定的方法,使得 MVVM 開發(fā)更加如虎添翼。
2.3 RxSwift 與 RxCocoa
- 前面配置的時(shí)候,我們會(huì)在 Swift 項(xiàng)目中引入 RxSwift、RxCocoa 這兩個(gè)庫(kù),他們的作用分別是:
- RxSwift:它只是基于 Swift 語(yǔ)言的 Rx 標(biāo)準(zhǔn)實(shí)現(xiàn)接口庫(kù),所以 RxSwift 里不包含任何 Cocoa 或者 UI 方面的類。
- RxCocoa:是基于 RxSwift 針對(duì)于 iOS 開發(fā)的一個(gè)庫(kù),它通過 Extension 的方法給原生的比如 UI 控件添加了 Rx 的特性,使得我們更容易訂閱和響應(yīng)這些控件的事件。
三、Observable 介紹
- Observable 作為 Rx 的根基,我們首先對(duì)它要有一些基本的了解。
3.1 Observable<T>
- Observable<T> 這個(gè)類就是 Rx 框架的基礎(chǔ),我們可以稱它為可觀察序列。它的作用就是可以異步地產(chǎn)生一系列的 Event(事件),即一個(gè) Observable<T> 對(duì)象會(huì)隨著時(shí)間推移不定期地發(fā)出 event(element : T) 這樣一個(gè)東西。
- 而且這些 Event 還可以攜帶數(shù)據(jù),它的泛型 <T> 就是用來(lái)指定這個(gè) Event 攜帶的數(shù)據(jù)的類型。
- 有了可觀察序列,我們還需要有一個(gè) Observer(訂閱者)來(lái)訂閱它,這樣這個(gè)訂閱者才能收到 Observable<T> 不時(shí)發(fā)出的 Event。
3.2 Event
- Event 就是一個(gè)枚舉,也就是說(shuō)一個(gè) Observable 是可以發(fā)出 3 種不同類型的 Event 事件:
next:next 事件就是那個(gè)可以攜帶數(shù)據(jù) <T> 的事件,可以說(shuō)它就是一個(gè)“最正?!钡氖录?br> error:error 事件表示一個(gè)錯(cuò)誤,它可以攜帶具體的錯(cuò)誤內(nèi)容,一旦 Observable 發(fā)出了 error event,則這個(gè) Observable 就等于終止了,以后它再也不會(huì)發(fā)出 event 事件了。
completed:completed 事件表示 Observable 發(fā)出的事件正常地結(jié)束了,跟 error 一樣,一旦 Observable 發(fā)出了 completed event,則這個(gè) Observable 就等于終止了,以后它再也不會(huì)發(fā)出 event 事件了。
3.3 Observable 與 Sequence比較
- 為更好地理解,我們可以把每一個(gè) Observable 的實(shí)例想象成于一個(gè) Swift 中的 Sequence:
- 即一個(gè) Observable(ObservableType)相當(dāng)于一個(gè)序列 Sequence(SequenceType)。
- ObservableType.subscribe(_:) 方法其實(shí)就相當(dāng)于 SequenceType.generate()
- 但它們之間還是有許多區(qū)別的:
- Swift 中的 SequenceType 是同步的循環(huán),而 Observable 是異步的。
- Observable 對(duì)象會(huì)在有任何 Event 時(shí)候,自動(dòng)將 Event 作為一個(gè)參數(shù)通過 ObservableType.subscribe(_:) 發(fā)出,并不需要使用 next 方法。
四、創(chuàng)建 Observable 序列
4.1 just() 方法
- 該方法通過傳入一個(gè)默認(rèn)值來(lái)初始化。
- 下面樣例我們顯式地標(biāo)注出了 observable 的類型為 Observable<Int>,即指定了這個(gè) Observable 所發(fā)出的事件攜帶的數(shù)據(jù)類型必須是 Int 類型的。
let observable = Observable<Int>.just(5)
4.2 of() 方法
- 該方法可以接受可變數(shù)量的參數(shù)(必需要是同類型的)
- 下面樣例中我沒有顯式地聲明出 Observable 的泛型類型,Swift 也會(huì)自動(dòng)推斷類型。
let observable = Observable.of("A", "B", "C")
4.3 from() 方法
- 該方法需要一個(gè)數(shù)組參數(shù)
- 下面樣例中數(shù)據(jù)里的元素就會(huì)被當(dāng)做這個(gè) Observable 所發(fā)出 event 攜帶的數(shù)據(jù)內(nèi)容,最終效果同上面餓 of() 樣例是一樣的。
let observable = Observable.from(["A", "B", "C"])
4.4 empty() 方法
- 該方法無(wú)需參數(shù)
- 該方法創(chuàng)建一個(gè)空內(nèi)容的 Observable 序列。
let observable = Observable<Int>.empty()
4.5 never() 方法
- 該方法無(wú)需參數(shù)
- 該方法創(chuàng)建一個(gè)永遠(yuǎn)不會(huì)發(fā)出 Event(也不會(huì)終止)的 Observable 序列。
let observable = Observable<Int>.never()
4.6 error() 方法
- 該方法需要一個(gè)Error對(duì)象
- 該方法創(chuàng)建一個(gè)不做任何操作,而是直接發(fā)送一個(gè)錯(cuò)誤的 Observable 序列。
enum MyError: Error {
case A
case B
}
let observable = Observable<Int>.error(MyError.A)
4.7 range() 方法
- 該方法通過指定起始和結(jié)束數(shù)值,創(chuàng)建一個(gè)以這個(gè)范圍內(nèi)所有值作為初始值的 Observable 序列。
- 下面樣例中,兩種方法創(chuàng)建的 Observable 序列都是一樣的。
//使用range()
let observable = Observable.range(start: 1, count: 5)
//使用of()
let observable = Observable.of(1, 2, 3 ,4 ,5)
4.8 repeatElement() 方法
- 該方法需要整數(shù)
- 該方法創(chuàng)建一個(gè)可以無(wú)限發(fā)出給定元素的 Event 的 Observable 序列(永不終止)。
let observable = Observable.repeatElement(1)
五、Subjects 介紹
- 即是訂閱者也是Observable(可觀察序列)
- Observable 在運(yùn)行時(shí)能動(dòng)態(tài)地“獲得”或者說(shuō)“產(chǎn)生”出一個(gè)新的數(shù)據(jù),再通過 Event 發(fā)送出去。比如:訂閱一個(gè)輸入框的輸入內(nèi)容,當(dāng)用戶每輸入一個(gè)字后,這個(gè)輸入框關(guān)聯(lián)的 Observable 就會(huì)發(fā)出一個(gè)帶有輸入內(nèi)容的 Event,通知給所有訂閱者。
5.1 Subjects 基本介紹
- Subjects 既是訂閱者,也是 Observable:
- 說(shuō)它是訂閱者,是因?yàn)樗軌騽?dòng)態(tài)地接收新的值。
- 說(shuō)它又是一個(gè) Observable,是因?yàn)楫?dāng) Subjects 有了新的值之后,就會(huì)通過 Event 將新值發(fā)出給他的所有訂閱者。
5.2 Subjects對(duì)象
- PublishRelay: PublishRelay 是對(duì)PublishSubject的包裝
- BehaviorRelay: BehaviorRelay是對(duì)BehaviorSubject的包裝
- ReplaySubject
- Variable
- 首先他們都是 Observable,他們的訂閱者都能收到他們發(fā)出的新的 Event。
直到 Subject 發(fā)出 .complete 或者 .error 的 Event 后,該 Subject 便終結(jié)了,同時(shí)它也就不會(huì)再發(fā)出 .next 事件。- 對(duì)于那些在 Subject 終結(jié)后再訂閱他的訂閱者,也能收到 subject 發(fā)出的一條 .complete 或 .error 的 event,告訴這個(gè)新的訂閱者它已經(jīng)終結(jié)了。
- 他們之間最大的區(qū)別只是在于:當(dāng)一個(gè)新的訂閱者剛訂閱它的時(shí)候,能不能收到 Subject 以前發(fā)出過的舊 Event,如果能的話又能收到多少個(gè)。
5.3 Subject 常用的幾個(gè)方法:
- onNext(:):是 on(.next(:)) 的簡(jiǎn)便寫法。該方法相當(dāng)于 subject 接收到一個(gè) .next 事件。
- onError(:):是 on(.error(:)) 的簡(jiǎn)便寫法。該方法相當(dāng)于 subject 接收到一個(gè) .error 事件。
- onCompleted():是 on(.completed) 的簡(jiǎn)便寫法。該方法相當(dāng)于 subject 接收到一個(gè) .completed 事件。
5.4 PublishRelay
- PublishRelay 是最普通的 Subject,它不需要初始值就能創(chuàng)建。
- PublishRelay 的訂閱者從他們開始訂閱的時(shí)間點(diǎn)起,可以收到訂閱后 Subject 發(fā)出的新 Event,而不會(huì)收到他們?cè)谟嗛喦耙寻l(fā)出的 Event。
5.5 BehaviorSubject
- BehaviorSubject 需要通過一個(gè)默認(rèn)初始值來(lái)創(chuàng)建。
- 當(dāng)一個(gè)訂閱者來(lái)訂閱它的時(shí)候,這個(gè)訂閱者會(huì)立即收到 BehaviorSubjects 上一個(gè)發(fā)出的 event。之后就跟正常的情況一樣,它也會(huì)接收到 BehaviorSubject 之后發(fā)出的新的 event。
5.6 ReplaySubject
- ReplaySubject 在創(chuàng)建時(shí)候需要設(shè)置一個(gè) bufferSize,表示它對(duì)于它發(fā)送過的 event 的緩存?zhèn)€數(shù)。
- 比如一個(gè) ReplaySubject 的 bufferSize 設(shè)置為 2,它發(fā)出了 3 個(gè) .next 的 event,那么它會(huì)將后兩個(gè)(最近的兩個(gè))event 給緩存起來(lái)。此時(shí)如果有一個(gè) subscriber 訂閱了這個(gè) ReplaySubject,那么這個(gè) subscriber 就會(huì)立即收到前面緩存的兩個(gè) .next 的 event。
- 如果一個(gè) subscriber 訂閱已經(jīng)結(jié)束的 ReplaySubject,除了會(huì)收到緩存的 .next 的 event 外,還會(huì)收到那個(gè)終結(jié)的 .error 或者 .complete 的 event。
5.7 Variable
- Variable 其實(shí)就是對(duì) BehaviorSubject 的封裝,所以它也必須要通過一個(gè)默認(rèn)的初始值進(jìn)行創(chuàng)建。
- Variable 具有 BehaviorSubject 的功能,能夠向它的訂閱者發(fā)出上一個(gè) event 以及之后新創(chuàng)建的 event。
- 不同的是,Variable 還把會(huì)把當(dāng)前發(fā)出的值保存為自己的狀態(tài)。同時(shí)它會(huì)在銷毀時(shí)自動(dòng)發(fā)送 .complete 的 event,不需要也不能手動(dòng)給 Variables 發(fā)送 completed 或者 error 事件來(lái)結(jié)束它。
- 簡(jiǎn)單地說(shuō)就是 Variable 有一個(gè) value 屬性,我們改變這個(gè) value 屬性的值就相當(dāng)于調(diào)用一般 Subjects 的 onNext() 方法,而這個(gè)最新的 onNext() 的值就被保存在 value 屬性里了,直到我們?cè)俅涡薷乃?/li>
5.8 BehaviorRelay是對(duì)BehaviorSubject的包裝,其事件也不太一樣
- BehaviorRelay 是作為 Variable 的替代者出現(xiàn)的。它的本質(zhì)其實(shí)也是對(duì) BehaviorSubject 的封裝,所以它也必須要通過一個(gè)默認(rèn)的初始值進(jìn)行創(chuàng)建。
- BehaviorRelay 具有 BehaviorSubject 的功能,能夠向它的訂閱者發(fā)出上一個(gè) event 以及之后新創(chuàng)建的 event。
- 與 BehaviorSubject 不同的是,不需要也不能手動(dòng)給 BehaviorReply 發(fā)送 completed 或者 error 事件來(lái)結(jié)束它(BehaviorRelay 會(huì)在銷毀時(shí)也不會(huì)自動(dòng)發(fā)送 .complete 的 event)。
- BehaviorRelay 有一個(gè) value 屬性,我們通過這個(gè)屬性可以獲取最新值。而通過它的 accept() 方法可以對(duì)值進(jìn)行修改。