map (變換)
把返回的數據轉換成更方便處理的格式再交給 Observer,是事件對象的直接變換(一對一變換)
Map操作符對原始Observable發射的每一項數據應用一個你選擇的函數,然後返回一個發射這些結果的Observable。
在map()
方法中加入參數 Func1<T,R>
,T
爲初始的事件類型,R
爲轉換過後的類型。
public class TestMapper implements Func1<T, R> {
}
之後複寫call()
方法,將T
類型轉換爲R
類型返回,就完成了事件類型的變換。
public List<Item> call(GankBeautyResult gankBeautyResult) {
List<GankBeauty> gankBeauties = gankBeautyResult.beauties;
List<Item> items = new ArrayList<>(gankBeauties.size());
SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SS'Z'");
SimpleDateFormat outputFormat = new SimpleDateFormat("yy/MM/dd HH:mm:ss");
for (GankBeauty gankBeauty : gankBeauties) {
Item item = new Item();
try {
Date date = inputFormat.parse(gankBeauty.createdAt);
item.description = outputFormat.format(date);
} catch (ParseException e) {
e.printStackTrace();
item.description = "unknown date";
}
item.imageUrl = gankBeauty.url;
items.add(item);
}
return items;
}
zip(壓合)
有的時候要訪問不同的接口,將接口糅合後轉換爲統一的格式後輸出(自家數據和第三方API廣告融合爲一個列表)。這種並行的異步操作處理比較麻煩,使用zip會簡單的多。
將不同接口並行請求獲取到的數據糅合在一起後再處理。
/**
*
* @param o1
* the first source Observable
* @param o2
* a second source Observable
* @param zipFunction
* a function that, when applied to an item emitted by each of the source Observables, results
* in an item that will be emitted by the resulting Observable
* @return an Observable that emits the zipped results
* @see <a href="http://reactivex.io/documentation/operators/zip.html">ReactiveX operators documentation: Zip</a>
*/
public static <T1, T2, R> Observable<R> zip(Observable<? extends T1> o1, Observable<? extends T2> o2, final Func2<? super T1, ? super T2, ? extends R> zipFunction) {
return just(new Observable<?>[] { o1, o2 }).lift(new OperatorZip<R>(zipFunction));
}
看下zip的參數和註釋,將T1
類型的Observable
和T2
類型的Observable
糅合爲R
類型的 Observable
。
subscription = Observable.zip(Network.getGankApi().getBeauties(200, 1).map(GankBeautyResultToItemsMapper.getInstance()),
Network.getZhuangbiApi().search("裝逼"),
new Func2<List<Item>, List<ZhuangbiImage>, List<Item>>() {
@Override
public List<Item> call(List<Item> gankItems, List<ZhuangbiImage> zhuangbiImages) {
List<Item> items = new ArrayList<Item>();
for (int i = 0; i < gankItems.size() / 2 && i < zhuangbiImages.size(); i++) {
items.add(gankItems.get(i * 2));
items.add(gankItems.get(i * 2 + 1));
Item zhuangbiItem = new Item();
ZhuangbiImage zhuangbiImage = zhuangbiImages.get(i);
zhuangbiItem.description = zhuangbiImage.description;
zhuangbiItem.imageUrl = zhuangbiImage.image_url;
items.add(zhuangbiItem);
}
return items;
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(observer);
在fun2() call
中實現自己的變換邏輯。(List中每一個item的類型)。本例子中T1
爲使用map轉換過的已經變成List<Item>
的Observable
,T2
爲List<ZhuangbiImage>
類型,將T1
,T2
糅合爲List<Item>
類型的R
,然後在觀察者中觀察。
flaMap (token)
出於安全性、性能等方面的考慮,多數服務器會有一些接口需要傳入 token 才能正確返回結果,而 token 是需要從另一個接口獲取的,這就需要使用兩步連續的請求才能獲取數據(①token -> ②目標數據)。使用 flatMap() 可以用較爲清晰的代碼實現這種連續請求,避免 Callback 嵌套的結構。
flatMap
可以實現一對多的轉化。
FlatMap將一個發射數據的Observable變換爲多個Observables,然後將它們發射的數據合併後放進一個單獨的Observable
FlatMap操作符使用一個指定的函數對原始Observable發射的每一項數據執行變換操作,這個函數返回一個本身也發射數據的Observable,然後FlatMap合併這些Observables發射的數據,最後將合併後的結果當做它自己的數據序列發射。
這個方法是很有用的,例如,當你有一個這樣的Observable:它發射一個數據序列,這些數據本身包含Observable成員或者可以變換爲Observable,因此你可以創建一個新的Observable發射這些次級Observable發射的數據的完整集合。
注意:FlatMap對這些Observables發射的數據做的是合併(merge
)操作,因此它們可能是交錯的。
final FakeApi fakeApi = Network.getFakeApi();
subscription = fakeApi.getFakeToken("fake_auth_code")
.flatMap(new Func1<FakeToken, Observable<FakeThing>>() {
@Override
public Observable<FakeThing> call(FakeToken fakeToken) {
return fakeApi.getFakeData(fakeToken);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<FakeThing>() {
@Override
public void call(FakeThing fakeData) {
swipeRefreshLayout.setRefreshing(false);
tokenTv.setText(getString(R.string.got_data, fakeData.id, fakeData.name));
}
}, new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
swipeRefreshLayout.setRefreshing(false);
Toast.makeText(getActivity(), R.string.loading_failed, Toast.LENGTH_SHORT).show();
}
});
retryWhen
BehaviorSubject
剩下兩個有空再更 = = 上述只是整理出自己的一些思路,代碼示例取自扔物線的github ,有錯誤請指出。
參考鏈接
[RxJavaSamples](https:// .com/rengwuxian/RxJavaSamples)
參考資料
RxJava Essentials 中文翻譯版
ReactiveX文檔中文翻譯