介紹
在項目中使用RxJava實現響應式編碼有一段時間,RxJava的強大,簡單的使用已經能夠滿足普通的開發需求,爲了記錄和加深自己的對RxJava的理解,寫這篇博客記錄一些自己對RxJava的使用和理解。
前期說明
下文用代碼說明一些操作符的功能和使用。
首先提供基本的可觀察對象,以下是基本的對象,後文中會根據需要進行修改。爲了簡化代碼使用lamdba表達式。
static Observable<String> sampleObserbableString(){
return Observable.create(subscriber -> {
for (int i = 0; i < 2; i++) {
subscriber.onNext("start "+ i);
Logger.d("start "+ i);
}
subscriber.onCompleted();
});
}
Map
代碼:先訪問得到可觀察的序列然後map轉換,給每個值加上“map”,打印結果。
sampleObservableString()
.map(new Func1<String, String>() {
@Override
public String call(String s) {
return s+" map";
}
})
.subscribe(new Subscriber<String>() {
@Override
public void onCompleted() {
Logger.d();
}
@Override
public void onError(Throwable e) {
Logger.d(e.toString());
}
@Override
public void onNext(String s) {
Logger.d(s);
}
});
可以看到,原來發射序列的onNext方法發送的值被map加工,然後觀察得到被map加工後的結果。
Log打印
04-20 14:48:21.835 [RxAndroidFragment:onNext:121]: start 0 map
04-20 14:48:21.836 [RxAndroidFragment:lambdasampleObservableString 1:130]: start 0
04-20 14:48:21.836 [RxAndroidFragment:onNext:121]: start 1 map
04-20 14:48:21.837 [RxAndroidFragment:lambdasampleObservableString 1:130]: start 1
04-20 14:48:21.839 [RxAndroidFragment:onCompleted:111]:
官方說明:
map:是對每個元素進行轉換。
flatMap
代碼:訂閱打印方式和map的代碼一樣,只修改調用了flatmap方法
sampleObservableString()
.flatMap(s -> sampleObservableString2())
.subscribe(打印結果)
可以看到,得到2*2=4次onNext打印結果。因爲每次原始數據的onNext都激發了flatmap中新數據源發射數據。這裏考慮有可能我兩個observable都是String類型對結果的影響,我改變代碼中的sampleObservableInteger2發射int包裝類,並訂閱。結果一樣也是4次打印結果。
04-20 15:02:28.727 [RxAndroidFragment:onNext:116]: from 0
04-20 15:02:28.727 [RxAndroidFragment:lambdasampleObservableString2 3:135]: from 0
04-20 15:02:28.728 [RxAndroidFragment:onNext:116]: from 1
04-20 15:02:28.728 [RxAndroidFragment:lambdasampleObservableString2 3:135]: from 1
04-20 15:02:28.729 [RxAndroidFragment:lambdasampleObservableString 2:125]: start 0
04-20 15:02:28.730 [RxAndroidFragment:onNext:116]: from 0
04-20 15:02:28.730 [RxAndroidFragment:lambdasampleObservableString2 3:135]: from 0
04-20 15:02:28.731 [RxAndroidFragment:onNext:116]: from 1
04-20 15:02:28.731 [RxAndroidFragment:lambdasampleObservableString2 3:135]: from 1
04-20 15:02:28.732 [RxAndroidFragment:lambdasampleObservableString 2:125]: start 1
04-20 15:02:28.733 [RxAndroidFragment:onCompleted:106]:
官方說明:
flatmap:提供一種鋪平序列的方式,然後合併這些Observables發射的數據,最後將合併後的結果作爲最終的Observable。
借用這篇博客的說明:
flatMap() 的原理是這樣的:
1. 使用傳入的事件對象創建一個 Observable 對象;2. 並不發送這個 Observable, 而是將它激活,於是它開始發送事件;3. 每一個創建出來的 Observable 發送的事件,都被匯入同一個 Observable ,而這個 Observable 負責將這些事件統一交給 Subscriber 的回調方法。這三個步驟,把事件拆成了兩級,通過一組新創建的 Observable 將初始的對象『鋪平』之後通過統一路徑分發了下去。而這個『鋪平』就是 flatMap() 所謂的 flat。
ConcatMap/FlatMapIterable
concatMap():函數解決了flatMap()的交叉問題(上圖能看到flatmap有交叉情況)提供了一種能夠把發射的值連續在一起的鋪平函數,而不是合併它們。由於代碼模擬比較簡單就不說用代碼說明。主要就是順序有了保證。
flatMapInterable():和flatMap()很像。僅有的本質不同是,它不是原始數據項和生成的Observables,而是將源數據兩兩結成對並生成Iterable。
debounce
debounce是過濾掉由Observable發射的速率過快的數據,這就需要修改我的發射源。
代碼如下:在發射3個元素的中間元素1時,休眠200毫秒,設置一個100毫秒間隔的debounce過濾
static Observable<String> sampleObservableString() {
return Observable.create(subscriber -> {
for (int i = 0; i < 3; i++) {
if (i==1) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
subscriber.onNext("start " + i);
Logger.d("start " + i);
}
subscriber.onCompleted();
});
}
sampleObservableString()
.debounce(100, TimeUnit.MILLISECONDS)
.subscribe(打印結果)
打印結果:得到了2次結果,中間那次被過濾掉了。因爲後兩次間隔太近。
04-20 16:09:59.817 [RxAndroidFragment:lambda
sampleObservableString 1:150]: start 0
04-20 16:09:59.916 20468-20524/com.demo.liyi.HttpDemo D/mDemo: [RxAndroidFragment:onNext:134]: start 0
04-20 16:10:01.818 [RxAndroidFragment:lambdasampleObservableString 1:150]: start 1
04-20 16:10:01.819 [RxAndroidFragment:lambdasampleObservableString 1:150]: start 2
04-20 16:10:01.819 [RxAndroidFragment:onNext:134]: start 2
04-20 16:10:01.820 [RxAndroidFragment:onCompleted:124]:
圖片說明:圖片可以更好的說明