RxJava(十二)combineLatest操作符的高級使用

RxJava系列文章目錄導(dǎo)讀:

一、RxJava create操作符的用法和源碼分析
二、RxJava map操作符用法詳解
三、RxJava flatMap操作符用法詳解
四、RxJava concatMap操作符用法詳解
五、RxJava onErrorResumeNext操作符實(shí)現(xiàn)app與服務(wù)器間token機(jī)制
六、RxJava retryWhen操作符實(shí)現(xiàn)錯(cuò)誤重試機(jī)制
七、RxJava 使用debounce操作符優(yōu)化app搜索功能
八、RxJava concat操作處理多數(shù)據(jù)源
九、RxJava zip操作符在Android中的實(shí)際使用場景
十、RxJava switchIfEmpty操作符實(shí)現(xiàn)Android檢查本地緩存邏輯判斷
十一、RxJava defer操作符實(shí)現(xiàn)代碼支持鏈?zhǔn)秸{(diào)用
十二、combineLatest操作符的高級使用
十三、RxJava導(dǎo)致Fragment Activity內(nèi)存泄漏問題
十四、interval、takeWhile操作符實(shí)現(xiàn)獲取驗(yàn)證碼功能


combineLatest 操作符用來將多個(gè)Observable發(fā)射的數(shù)據(jù)組裝起來然后在發(fā)射. 通過Func類來組裝多個(gè)Observable發(fā)射的數(shù)據(jù), 等到最后一個(gè)Observable發(fā)射數(shù)據(jù)了, 然后把所有發(fā)射的數(shù)據(jù)交給Fun進(jìn)行組合, 然后把組合后的數(shù)據(jù)發(fā)射出去.

看到網(wǎng)上絕大部分都是用 combineLatest 來做Android表單的校驗(yàn), 總感覺有點(diǎn)大材小用. 如只有表單都只有值了了, 提交按鈕才可用:

    Observable<CharSequence> etFeedbackInputObservable = RxTextView.textChanges(mEditFeedbackInput).skip(1);
    Observable<CharSequence> etFeedbackEmailObservable = RxTextView.textChanges(mEditFeedbackEmail).skip(1);
    Observable.combineLatest(etFeedbackInputObservable, etFeedbackEmailObservable, new Func2<CharSequence, CharSequence, Boolean>() {
        @Override
        public Boolean call(CharSequence charSequence, CharSequence charSequence2) {
            boolean inputValid = !TextUtils.isEmpty(charSequence);
            boolean emailValid = !TextUtils.isEmpty(charSequence2);
            return inputValid && emailValid;
        }
    }).subscribe(new Observer<Boolean>() {
        @Override
        public void onCompleted() {
            Logger.d("onCompleted");
        }

        @Override
        public void onError(Throwable e) {
            Logger.e("onError-->" + e.toString());
        }

        @Override
        public void onNext(Boolean aBoolean) {
            //讓提交表單可以單擊
            mButtonSendFeedback.setEnabled(aBoolean);
        }
    });

在實(shí)際的項(xiàng)目開發(fā)中, combineLatest操作除了可以做一些簡單的表單校驗(yàn), 還可以做更加復(fù)雜的業(yè)務(wù)場景, 最重要的是遇到了這種場景能夠用RxJava操作符來解決.

再上家公司有這樣一個(gè)業(yè)務(wù)場景: 一個(gè)用戶查看自己的訂單列表(該用戶是藝術(shù)家在平臺上賣藝術(shù)品的), 界面除了展示訂單的基本信息, 還需要在Item的底部展示是哪個(gè)用戶購買的(展示購買者的頭像和名字), 但是后臺返回的JSON數(shù)據(jù)對應(yīng)的Bean如下所示 :

public class JsonOrderPage<Order> {
    public List<Order> data;
    public Paging paging;
}

似乎感覺也沒什么, 但是后臺返回的Order對象里對于購買者的信息只有購買者的id, 但是界面上需要顯示購買者的名字和頭像. 說白了需要根據(jù)購買者的id來獲取購買者的信息. 如果后端返回的僅僅是個(gè)List就好了, 那就用flatMap操作符很好的解決了. 當(dāng)然最直觀的解決方式就是for循序環(huán), 如下所示:

Observable<JsonOrderPage> observableUser = xxx;
observableJsonOrderPage.flatMap(new Func1<JsonOrderPage, Observable<JsonOrderPage>>() {
    @Override
    public Observable<JsonOrderPage> call(JsonOrderPage page) {
        List<Order> orders = page.getData();
        for (Order order : orders) {
            //同步請求獲取購買者的信息
            User buyer = userApi.getUserInfoById(order.getBuyer().getBuyerId());
            //把獲取的購買者信息賦值給Order
            order.setBuyer(buyer);
        }
    }
})

雖然實(shí)現(xiàn)了功能, 但是總覺得不爽, 都用了RxJava這么牛逼的框架, 還要用for循環(huán)操作. 有沒有比較優(yōu)雅的方式來實(shí)現(xiàn)這種需求呢?

**這種需求就是 對A對象上的某個(gè)List屬性進(jìn)行RxJava操作, 然后把操作的結(jié)果再重新賦給原來的A對象. **

我們知道對A對象的List進(jìn)行操作, RxJava操作后返回的就是List, 無法獲取原來的A對象, 除非我們先獲取A對象, 然后通過變量保存下, 當(dāng)處理完List后,把最終的List賦值給A對象, 這種方法還不如第一種呢? 我想的是有沒有一種途徑全程用RxJava操作符來做.

這種需求還是很多的, 比如返回一個(gè)用戶對象(User), 里面有個(gè)List屬性表示他的好友, 但是關(guān)于好友的信息只有id. 界面展示的他的好友信息.

類似這樣的需求, 需要對數(shù)據(jù)的某個(gè)子數(shù)據(jù)進(jìn)行單獨(dú)處理, 可以使用combineLatest來優(yōu)雅的實(shí)現(xiàn) :

userApi = ApiServiceFactory.createService(UserApi.class);
//獲取用戶信息
userApi.fetchUserInfo(null)
        .flatMap(new Func1<User, Observable<User>>() {
            @Override
            public Observable<User> call(User user) {
                printLog(tvLogs, "----fetch a user---- \n", getUserString(user));
                
                return fetchFriendsInfo(user);
            }
        })
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Action1<User>() {
            @Override
            public void call(User user) {
                printLog(tvLogs, "----process his friends by id---- \n", getUserString(user));
            }
        }, new Action1<Throwable>() {
            @Override
            public void call(Throwable throwable) {
                throwable.printStackTrace();
            }
        });



//這個(gè)方法才是實(shí)現(xiàn)的核心
private Observable<User> fetchFriendsInfo(User user) {
    
    //保存User的數(shù)據(jù)
    Observable<User> observableUser = Observable.just(user);
    
    //對User的好友列表進(jìn)行單獨(dú)處理
    Observable<List<User>> observableUsers = Observable.from(user.getFriends())
            .flatMap(new Func1<User, Observable<User>>() {
                @Override
                public Observable<User> call(User user) {
                    //根據(jù)好友ID獲取更完整的信息
                    return userApi.fetchUserInfo(user.getId() + "");
                }
            })
            .toList();

    //對用戶User信息和他的好友信息進(jìn)行合并.
    return Observable.combineLatest(observableUser, observableUsers, new Func2<User, List<User>, User>() {
        @Override
        public User call(User user, List<User> users) {
            user.setFriends(users);
            return user;
        }
    });
}

上面的代碼還是很簡單的, 注釋也比較詳細(xì). 大致的意思就是把User信息分為兩個(gè)部分:

一部分是User的基本信(Observable<User>), 一部分是User好友列表(Observable<List<User>>) 然后把兩個(gè)最終數(shù)據(jù)進(jìn)行組合就是我們最終需要的數(shù)據(jù)了.

我在github上已經(jīng)寫了相關(guān)例子, 運(yùn)行效果如下所示:

這里寫圖片描述

本文的例子放在github上https://github.com/chiclaim/android-sample/tree/master/rxjava

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本篇文章介主要紹RxJava中操作符是以函數(shù)作為基本單位,與響應(yīng)式編程作為結(jié)合使用的,對什么是操作、操作符都有哪些...
    嘎啦果安卓獸閱讀 2,991評論 0 10
  • 注:只包含標(biāo)準(zhǔn)包中的操作符,用于個(gè)人學(xué)習(xí)及備忘參考博客:http://blog.csdn.net/maplejaw...
    小白要超神閱讀 2,376評論 2 8
  • 作者: maplejaw本篇只解析標(biāo)準(zhǔn)包中的操作符。對于擴(kuò)展包,由于使用率較低,如有需求,請讀者自行查閱文檔。 創(chuàng)...
    maplejaw_閱讀 46,218評論 8 93
  • 創(chuàng)建操作 用于創(chuàng)建Observable的操作符Create通過調(diào)用觀察者的方法從頭創(chuàng)建一個(gè)ObservableEm...
    rkua閱讀 1,957評論 0 1
  • 前言 按照官方的分類,操作符大致分為以下幾種: Creating Observables(Observable的創(chuàng)...
    小玉1991閱讀 1,117評論 0 1

友情鏈接更多精彩內(nèi)容