Android RxJava操作符的學習---變換操作符
阿新 • • 發佈:2018-11-09
3.2 變換操作符
3.2.1.作用
對事件序列中的事件 / 整個事件序列 進行加工處理(即變換),使得其轉變成不同的事件 / 整個事件序列
- 具體原理
3.2.2.作用型別
-
應用場景
巢狀回撥(Callback hell
) -
根據上述應用場景,常見的變換操作符型別包括:
3.2.3. 應用場景 & 對應操作符 介紹
- 下面,我將對
RxJava2
中的變換操作符進行逐個講解 - 注:在使用
RxJava 2
操作符前,記得在專案的Gradle
中新增依賴:
dependencies { compile 'io.reactivex.rxjava2:rxandroid:2.0.1' compile 'io.reactivex.rxjava2:rxjava:2.0.7' // 注:RxJava2 與 RxJava1 不能共存,即依賴不能同時存在 }
Map()
- 作用
對 被觀察者傳送的每1個事件都通過 指定的函式 處理,從而變換成另外一種事件
即, 將被觀察者傳送的事件轉換為任意的型別事件。
- 原理
- 應用場景
資料型別轉換
- 具體使用
下面以將 使用Map()
將事件的引數從 整型 變換成 字串型別 為例子說明
// 採用RxJava基於事件流的鏈式操作 Observable.create(new ObservableOnSubscribe<Integer>() { // 1. 被觀察者傳送事件 = 引數為整型 = 1、2、3 @Override public void subscribe(ObservableEmitter<Integer> emitter) throws Exception { emitter.onNext(1); emitter.onNext(2); emitter.onNext(3); } // 2. 使用Map變換操作符中的Function函式對被觀察者傳送的事件進行統一變換:整型變換成字串型別 }).map(new Function<Integer, String>() { @Override public String apply(Integer integer) throws Exception { return "使用 Map變換操作符 將事件" + integer +"的引數從 整型"+integer + " 變換成 字串型別" + integer ; } }).subscribe(new Consumer<String>() { // 3. 觀察者接收事件時,是接收到變換後的事件 = 字串型別 @Override public void accept(String s) throws Exception { Log.d(TAG, s); } });
- 測試結果
從上面可以看出,map()
將引數中的 Integer
型別物件轉換成一個 String
型別 物件後返回
同時,事件的引數型別也由
Integer
型別變成了String
型別
FlatMap()
-
作用:將被觀察者傳送的事件序列進行 拆分 & 單獨轉換,再合併成一個新的事件序列,最後再進行傳送
-
原理
- 為事件序列中每個事件都建立一個
Observable
物件; - 將對每個 原始事件 轉換後的 新事件 都放入到對應
Observable
物件; - 將新建的每個
Observable
都合併到一個 新建的、總的Observable
- 新建的、總的
Observable
物件 將 新合併的事件序列 傳送給觀察者(Observer
)
-
應用場景
無序的將被觀察者傳送的整個事件序列進行變換 -
具體使用
// 採用RxJava基於事件流的鏈式操作
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
}
// 採用flatMap()變換操作符
}).flatMap(new Function<Integer, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(Integer integer) throws Exception {
final List<String> list = new ArrayList<>();
for (int i = 0; i < 3; i++) {
list.add("我是事件 " + integer + "拆分後的子事件" + i);
// 通過flatMap中將被觀察者生產的事件序列先進行拆分,再將每個事件轉換為一個新的傳送三個String事件
// 最終合併,再發送給被觀察者
}
return Observable.fromIterable(list);
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.d(TAG, s);
}
});
-
測試結果
注:新合併生成的事件序列順序是無序的,即 與舊序列傳送事件的順序無關
ConcatMap()
-
作用:類似
FlatMap()
操作符 -
與
FlatMap
()的 區別在於:拆分 & 重新合併生成的事件序列 的順序 = 被觀察者舊序列生產的順序 -
原理
-
應用場景
有序的將被觀察者傳送的整個事件序列進行變換 -
具體使用
// 採用RxJava基於事件流的鏈式操作
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
}
// 採用concatMap()變換操作符
}).concatMap(new Function<Integer, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(Integer integer) throws Exception {
final List<String> list = new ArrayList<>();
for (int i = 0; i < 3; i++) {
list.add("我是事件 " + integer + "拆分後的子事件" + i);
// 通過concatMap中將被觀察者生產的事件序列先進行拆分,再將每個事件轉換為一個新的傳送三個String事件
// 最終合併,再發送給被觀察者
}
return Observable.fromIterable(list);
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.d(TAG, s);
}
});
-
測試結果
注:新合併生成的事件序列順序是有序的,即 嚴格按照舊序列傳送事件的順序
Buffer()
-
作用
定期從 被觀察者(Obervable
)需要傳送的事件中 獲取一定數量的事件 & 放到快取區中,最終傳送 -
原理
- 應用場景
快取被觀察者傳送的事件
- 具體使用
那麼,Buffer()
每次是獲取多少個事件放到快取區中的呢?下面我將通過一個例子來說明
// 被觀察者 需要傳送5個數字
Observable.just(1, 2, 3, 4, 5)
.buffer(3, 1) // 設定快取區大小 & 步長
// 快取區大小 = 每次從被觀察者中獲取的事件數量
// 步長 = 每次獲取新事件的數量
.subscribe(new Observer<List<Integer>>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(List<Integer> stringList) {
//
Log.d(TAG, " 快取區裡的事件數量 = " + stringList.size());
for (Integer value : stringList) {
Log.d(TAG, " 事件 = " + value);
}
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "對Error事件作出響應" );
}
@Override
public void onComplete() {
Log.d(TAG, "對Complete事件作出響應");
}
});
- 測試結果
- 過程解釋
下面,我將通過一個圖來解釋Buffer()
原理 & 整個例子的結果