1. 程式人生 > >RxJava2 轉換操作符之Map()方法

RxJava2 轉換操作符之Map()方法

前言:
本文將在Rx官方解釋的基礎上,再融合其它國內講解的文章。儘量用最簡單的,易懂的方式,解釋map()操作符。解釋的過程,以問答的形式,先從整體簡單解釋入手,並配上能跑的示例程式碼(0 warnings, 0 errors)。先知道能做什麼和怎麼做,再講原理,並儘量做到中英融合解釋。(建議用PC端閱讀,圖片可以放大。排版,也有利於閱讀)

一、需要了解的知識點:
Observer與Consumer的區別:後者是簡化了前者,減去了許多回調介面。注意,重要的事說三遍:他們都是充當觀察者角色他們都是充當觀察者角色他們都是充當觀察者角色。其它詳情,可以參考這篇:Observer與Consumer的區別

二、Map的操作流程圖解
上面的線,表示原始資料。下面的線,表示轉換後的資料。中間的塊,代表轉換過程。兩條線的結尾有一小條豎線,表示結束。箭頭的方向,從左到右,表示執行過程,是從左到右跑的。
這裡寫圖片描述

三、學習之前,先來看看,一些常見的問題及解答,基於問題來學習Map操作符。

1、map()操作符能做什麼?
答:map()操作符用於轉換一組資料。至於怎麼轉換,由你自己指定。比如,簡單的對資料進行加減乘除處理。又比如,將某一個類轉成另一個類。又比如,將一組User類物件(userName是User類的一個欄位),轉成一組userName物件。

2、那它是什麼時候開始轉換,或者說,是如何觸發轉換事件的?然後,又是在哪裡轉換的?最後,它又是如何轉換的?


答:問的有點多。。一個一個來。

  • map()是什麼時候開始轉換的?(即如何觸發轉換事件),一旦,可(被)觀察者(Observable),被觀察者(Observer或者Consumer)訂閱了,就開始進行轉換。那問題來了,怎麼訂閱?通過設定監聽回撥,來建立訂閱關係。
  • 那在哪裡進行轉換處理呢?,在這個R apply(@NonNull T t) 方法裡進行處理。RT 都是泛型。
  • 那它又是如何實現轉換的?,從上一條可以看出,R apply(@NonNull T t) 方法,有兩個泛型。傳入apply方法的T是原資料型別,由apply方法返回的R型別,即是轉換後的型別。具體的轉換邏輯,在apply()方法裡面,由你自己實現。

3、說了這麼多,示例程式碼呢?要複製貼上就能跑的那種(0 warnings,0 errors)。
答:好,但你得先配置RxJava2庫。同時,在看之前,給你點提示,助你閱讀。因為RxJava2是基於觀察者模式,以響應流的方式對資料進行非同步請求處理。所以,你在閱讀程式碼時,只要遵循簡單的從上到下的思考邏輯即可。

      public static void actionMap() {

        List<Integer> list = Arrays.asList(1,2,3);

        Observable.fromIterable(list)
                .map(new Function<Integer, String>() {
                    @Override
                    public String apply(Integer integer) throws Exception {
                        // Converts integer into string.
                        return String.valueOf(integer);
                    }
                }).subscribe(new Consumer<String>() {
                    @Override
                    public void accept(String s) throws Exception {
                        // prints the converted value
                        log("accept=" + s );
                    }
                });
    }

我們先從上到下來分析這段程式碼。

首先,Observable(被觀察者),通過呼叫fromIterable來接收一個list,做為資料來源(原始資料,被轉換的資料)。fromIterable在接收到資料來源後,會返回呼叫它的Observable物件。

接著,Observable會呼叫map()操作符。注意啦!整容部分要開始啦。 map()操作符,接收一個函式式介面Function< T , R>。這個介面帶有兩個泛型引數,T是要被整容的資料的型別,R則是被整容後的結果資料的型別。然後,只要訂閱關係被建立,map()操作符就會通過呼叫Function接口裡面唯一的方法 R apply(@NonNull T t)。這個方法的作用,就像手術室的作用。T是被整容前的資料。R則是整容後的資料。T–> 整容手術室apply()–> R,就是這樣一個過程。那麼,這個整容後的資料,交給誰呢?在return R後,R就被Observable給接收了,同時map()方法本身,也會返回一個Observable物件。。。注意,apply()返回的是R,map()返回的才是Observable

最後,要做的就是建立訂閱關係。因為map()返回了一個Observable,所以,就可以再通過Observable,來呼叫一個subscribe方法,建立訂閱關係。subscribe方法接收一個介面做為引數(Observer or Consumer)。程式碼片段中,以一個Consumer為demo。可以看到Consumer接口裡面有一個void accept(T t) 方法。這個方法裡面有一個T型別,這個T型別,即是被整容後的資料的型別。變數t,則是被整容後的資料。剩下的,你想要對這個被整容後,變漂亮的t做什麼下流的事,我就不管了。

上面部分是以Consumer為例,再舉一個以Observer為例的,同樣地,讓我們來看程式碼:

     Observable.fromIterable(list)
                .map(new Function<Integer, String>() {
                    @Override
                    public String apply(Integer integer) throws Exception {
                        // Converts integer into string.
                        log("apply");
                        return String.valueOf(integer);
                    }
                }).subscribe(new Observer<String>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        // d.dispose(); Cancel Converts
                        log("onSubscribe" );
                    }

                    @Override
                    public void onNext(String s) {
                        // get 's' from apply().
                        log("onNext=" + s );
                    }

                    @Override
                    public void onError(Throwable e) {
                        // invoked when an exception occurred.
                        // if onError be invoked, The onComplete will never be invoked.
                        // it means the Observer will invoke either the onError or the onComplete.
                        log("onError");
                    }

                    @Override
                    public void onComplete() {
                        // invoked when transforming job done.
                        log("onComplete");
                    }
                });

這是輸出的資訊:

D/TransformingOperations: onSubscribe 
D/TransformingOperations: apply  
D/TransformingOperations: onNext=1 
D/TransformingOperations: apply 
D/TransformingOperations: onNext=2  
D/TransformingOperations: apply 
D/TransformingOperations: onNext=3  
D/TransformingOperations: onComplete 

前面部分程式碼,跟Consumer的沒區別。重點看Observer回撥部分。可以這樣理解,apply()方法每執行一次,onNext就會被執行一次。直到所有資料都被轉換成功後,onComplete方法就會被呼叫。如果,在這個轉換的過程中,發生什麼異常。那麼,就不會執行onComplete,而是執行onError方法。然後,onSubscribe最先被呼叫,所以,可以在這裡做一些準備工作。至於執行緒切換排程的,不屬於操作符的講解範疇,這裡就不做示例解釋了。

本篇到此結束,如果覺得,問答過程或是分析過程,有什麼不易理解,或不到位的。可以在評論區,指出。歡迎批評指正。

注意:
這個庫裡面有很多東西,RxJava2的轉換操作符部分的demo位於:com.lyf.okmvp.demo.rxjava2包下的TransformingOperations類裡面。

用法:
1、直接在com.lyf.okmvp.ui包下的MainActivity類裡的onCreate()方法裡面,直接呼叫:

TransformingOperations.actionMap(); // 靜態方法。

2、也可以複製TransformingOperations類到你的專案裡,去為所欲為。但前提時,你得有配置過RxJava和RxAndroid。配置方法,自行百度,或參考我的OkMVP庫。