【Android】RxJava的使用(三)轉(zhuǎn)換——map、flatMap

前兩篇Android RxJava的使用(一)基本用法、Android RxJava的使用(二)Action介紹了RxJava的基本用法,對(duì)Rxjava還不了解的請(qǐng)先看以上兩篇。這篇為大家講解RxJava中map和flatMap的使用。

參考:給 Android 開(kāi)發(fā)者的 RxJava 詳解
(本文部分內(nèi)容引用自該博客)

回顧

前兩篇為大家介紹了使用RxJava打印多個(gè)字符串的方法

     Observable.just("Hellow", "Wrold").subscribe(new Action1<String>() {
          @Override
          public void call(String s) {
              Log.i(TAG, s);
          }
      });

這樣的例子基本沒(méi)有實(shí)際用處,只是為大家演示如何使用Rxjava。今天就拋開(kāi)這個(gè)例子。

map

在使用map之前要先說(shuō)道一個(gè)接口:Func1,F(xiàn)unc1和上一篇提到的Action1相似。Func1 和 Action的區(qū)別在于, Func1 包裝的是有返回值的方法。
接下來(lái)就是map的用法,看代碼更直觀點(diǎn);
例:得到多個(gè)Student對(duì)象中的name,保存到nameList中

        Observable.just(student1, student2, student2)
                //使用map進(jìn)行轉(zhuǎn)換,參數(shù)1:轉(zhuǎn)換前的類型,參數(shù)2:轉(zhuǎn)換后的類型
                .map(new Func1<Student, String>() {
                    @Override
                    public String call(Student i) {
                        String name = i.getName();//獲取Student對(duì)象中的name
                        return name;//返回name
                    }
                })
                .subscribe(new Action1<String>() {
                    @Override
                    public void call(String s) {
                        nameList.add(s);
                    }
                });

可以看到Observable中原來(lái)的參數(shù)是Student對(duì)象,而最后我們需要的是name,這里使用了map來(lái)實(shí)現(xiàn)這一轉(zhuǎn)換的過(guò)程。當(dāng)然,map可以多次使用。

        //多次使用map,想用幾個(gè)用幾個(gè)
        Observable.just("Hello", "World")
                .map(new Func1<String, Integer>() {//將String類型的轉(zhuǎn)化為Integer類型的哈希碼
                    @Override
                    public Integer call(String s) {
                        return s.hashCode();
                    }
                })
                .map(new Func1<Integer, String>() {//將轉(zhuǎn)化后得到的Integer類型的哈希碼再轉(zhuǎn)化為String類型
                    @Override
                    public String call(Integer integer) {
                        return integer.intValue() + "";
                    }
                })
                .subscribe(new Action1<String>() {
                    @Override
                    public void call(String s) {
                        Log.i(TAG, s);
                    }
                });

flatMap

flatMap是一個(gè)比教難理解的一個(gè)轉(zhuǎn)換,在這里先假設(shè)一個(gè)需求,需要打印多個(gè)Student所學(xué)的課程。這跟之前獲取Student的name又不同了,這里先確定一下關(guān)系,一個(gè)Student類中只有一個(gè)name,而一個(gè)Student卻有多門課程(Course),Student我們可以理解成這樣:

    /**
     * 學(xué)生類
     */
    class Student {
        private String name;//姓名
        private List<Course> coursesList;//所修的課程
        ...
    }
    /**
     * 課程類
     */
    class  Course {
        private String name;//課程名
        private String id;
        ...
    }

如果使用map來(lái)實(shí)現(xiàn)打印所有學(xué)生所修個(gè)課程名,實(shí)現(xiàn)的代碼是這樣的:

        List<Student> students = new ArrayList<Student>();
        students.add...
        ...

        Action1<List<Course>> action1 = new Action1<List<Course>>() {
            @Override
            public void call(List<Course> courses) {
                //遍歷courses,輸出cuouses的name
                 for (int i = 0; i < courses.size(); i++){
                    Log.i(TAG, courses.get(i).getName());
                }
            }
        };
        Observable.from(students)
                .map(new Func1<Student, List<Course>>() {
                    @Override
                    public List<Course> call(Student student) {
                        //返回coursesList
                        return student.getCoursesList();
                    }
                })
                .subscribe(action1);

可以看到,在Action1中出現(xiàn)了for來(lái)循環(huán)打印課程名,使用RxJava就是為了剔除這樣的嵌套結(jié)構(gòu),使得整體的邏輯性更強(qiáng)。這時(shí)候就可以使用flatMap了,使用flatMap實(shí)現(xiàn)的代碼是這樣的:

        List<Student> students = new ArrayList<Student>();
        students.add...
        ...

        Observable.from(students)
                .flatMap(new Func1<Student, Observable<Course>>() {
                    @Override
                    public Observable<Course> call(Student student) {
                        return Observable.from(student.getCoursesList());
                    }
                })
                .subscribe(new Action1<Course>() {
                    @Override
                    public void call(Course course) {
                        Log.i(TAG, course.getName());
                    }
                });

這樣就實(shí)現(xiàn)了跟上面代碼一樣的效果,看起來(lái)有點(diǎn)懵?確實(shí),flatMap理解起來(lái)有點(diǎn)繞,剛接觸flatMap的時(shí)候我也是懵逼一個(gè)。下面我將flatMap的示意圖,希望能幫助理解:


flatMap示意圖

由上圖可以看出Student1、Student2經(jīng)過(guò)flatMap后,按順序依次經(jīng)歷了Observable1、Observable2,分別轉(zhuǎn)化為Course。最后按順序得到Course1、Course2、Course3、Course4、Course5、Course6,其中1-3由Student1得到,4-6由Student2得到。
結(jié)合代碼和示意圖,是不是對(duì)flatMap有了一定的理解。

注意:FlatMap對(duì)這些Observables發(fā)射的數(shù)據(jù)做的是合并(merge)操作,因此它們可能是交錯(cuò)的。也就說(shuō),傳入的順序可能跟出來(lái)的順序不一樣。
如果要保證順的的話,可以使用concatMap。

其他操作符

除了map和flatMap之外,還有其他操作符以供使用。這里就不一一列舉他們的用法了,其他常用的操作符如下:

filter:集合進(jìn)行過(guò)濾
each:遍歷集合
take:取出集合中的前幾個(gè)
skip:跳過(guò)前幾個(gè)元素

更多操作符

小結(jié)

看完map、flatMap后,慢慢能看到RxJava的實(shí)際用處了。不過(guò)只是這點(diǎn)功能的RxJava是遠(yuǎn)遠(yuǎn)不能滿足我們的需求,更多的用法我只能在后面更新了。今天就到這里吧?。?!

以上有錯(cuò)誤之處感謝指出

更多:
Android RxJava的使用(四)線程控制 —— Scheduler

參考:給 Android 開(kāi)發(fā)者的 RxJava 詳解
(本文部分內(nèi)容引用自該博客)

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

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

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