RxJava進階實例 zip(壓合)

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類型的ObservableT2類型的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,T2List<ZhuangbiImage>類型,將T1T2糅合爲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文檔中文翻譯

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章