1. 程式人生 > >Android RxJava操作符的學習---組合合併操作符---合併資料來源並展示

Android RxJava操作符的學習---組合合併操作符---合併資料來源並展示

1. 需求場景

 

 

2. 功能說明

即,同時向2個數據源獲取資料 -> 合併資料 -> 統一展示到客戶端


3. 具體實現

此處採用Merge() & Zip()操作符進行講解,其中:

  • Merge()例子 :實現較為簡單的從(網路 + 本地)獲取資料 & 統一展示
  • Zip()例子:結合RetrofitRxJava,實現較為複雜的合併2個網路請求向2個伺服器獲取資料 & 統一展示

3.1 採用 Merge()操作符

  • 具體實現
// 用於存放最終展示的資料
        String result = "資料來源來自 = " ;
       
        /*
         * 設定第1個Observable:通過網路獲取資料
         * 此處僅作網路請求的模擬
         **/
        Observable<String> network = Observable.just("網路");

        /*
         * 設定第2個Observable:通過本地檔案獲取資料
         * 此處僅作本地檔案請求的模擬
         **/
        Observable<String> file = Observable.just("本地檔案");


        /*
         * 通過merge()合併事件 & 同時傳送事件
         **/
        Observable.merge(network, file)
                .subscribe(new Observer<String>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(String value) {
                        Log.d(TAG, "資料來源有: "+ value  );
                        result += value + "+";
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.d(TAG, "對Error事件作出響應");
                    }

                    // 接收合併事件後,統一展示
                    @Override
                    public void onComplete() {
                        Log.d(TAG, "獲取資料完成");
                        Log.d(TAG,  result  );
                    }
                });
  • 測試結果

3.2 採用Zip()操作符

  • 功能說明
    在該例中,我將結合結合 RetrofitRxJava,實現:

    1. 從不同資料來源(2個伺服器)獲取資料,即 合併網路請求的傳送
    2. 統一顯示結果
  • 實現方案
    採用Get方法 對 金山詞霸API 傳送2個網路請求(將英文翻譯成中文,翻譯2次) & 將2次翻譯的結果一起顯示。

採用 Gson 進行資料解析

步驟說明

  1. 新增依賴
  2. 建立 接收伺服器返回資料 的類
  3. 建立 用於描述網路請求 的介面
  4. 建立 Retrofit 例項
  5. 建立 網路請求介面例項 並 配置網路請求引數
  6. 傳送網路請求
  7. 傳送網路請求
  8. 對返回的資料進行處理
  • 步驟實現

步驟1: 新增依賴

a. 在 Gradle加入Retrofit庫的依賴

build.gradle

dependencies {

// Android 支援 Rxjava
// 此處一定要注意使用RxJava2的版本
compile 'io.reactivex.rxjava2:rxjava:2.0.1'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'

// Android 支援 Retrofit
compile 'com.squareup.retrofit2:retrofit:2.1.0'

// 銜接 Retrofit & RxJava
// 此處一定要注意使用RxJava2的版本
compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'

// 支援Gson解析
compile 'com.squareup.retrofit2:converter-gson:2.1.0'

}

b. 新增 網路許可權
AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET"/>

步驟2:建立 接收伺服器返回資料 的類

  • 金山詞霸API 的資料格式說明如下:
// URL模板
http://fy.iciba.com/ajax.php

// URL例項
http://fy.iciba.com/ajax.php?a=fy&f=auto&t=auto&w=hello%20world

// 引數說明:
// a:固定值 fy
// f:原文內容型別,日語取 ja,中文取 zh,英語取 en,韓語取 ko,德語取 de,西班牙語取 es,法語取 fr,自動則取 auto
// t:譯文內容型別,日語取 ja,中文取 zh,英語取 en,韓語取 ko,德語取 de,西班牙語取 es,法語取 fr,自動則取 auto
// w:查詢內容
  • 根據 金山詞霸API 的資料格式,建立 接收伺服器返回資料 的類:

為了演示是兩個網路請求,所以對應設定2個接收伺服器的資料類

<-- Translation1.java -->
public class Translation1 {
    private int status;
    private content content;
    private static class content {
        private String from;
        private String to;
        private String vendor;
        private String out;
        private int errNo;
    }

   //定義 輸出返回資料 的方法
    public String show() {

        return ("第1次翻譯=" + content.out);

    }
}

<-- Translation2.java -->
public class Translation2 {
    private int status;
    private content content;
    private static class content {
        private String from;
        private String to;
        private String vendor;
        private String out;
        private int errNo;
    }

 //定義 輸出返回資料 的方法
    public String show() {

        return ("第2次翻譯=" + content.out);

    }
}

步驟3:建立 用於描述網路請求 的介面

採用 註解 + Observable<...>介面描述 網路請求引數

GetRequest_Interface.java

public interface GetRequest_Interface {

    // 網路請求1
    @GET("ajax.php?a=fy&f=auto&t=auto&w=hi%20world")
    Observable<Translation1> getCall();

    // 網路請求2
    @GET("ajax.php?a=fy&f=auto&t=auto&w=hi%20china")
    Observable<Translation2> getCall_2();

    // 註解裡傳入 網路請求 的部分URL地址
    // Retrofit把網路請求的URL分成了兩部分:一部分放在Retrofit物件裡,另一部分放在網路請求接口裡
    // 如果接口裡的url是一個完整的網址,那麼放在Retrofit物件裡的URL可以忽略
    // 採用Observable<...>介面
    // getCall()是接受網路請求資料的方法

}

接下來的步驟均在MainActivity.java內實現(請看註釋)

MainActivity.java

public class MainActivity extends AppCompatActivity {


        private static final String TAG = "Rxjava";


        // 定義Observable介面型別的網路請求物件
        Observable<Translation1> observable1;
        Observable<Translation2> observable2;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            // 步驟1:建立Retrofit物件
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl("http://fy.iciba.com/") // 設定 網路請求 Url
                    .addConverterFactory(GsonConverterFactory.create()) //設定使用Gson解析(記得加入依賴)
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 支援RxJava
                    .build();

            // 步驟2:建立 網路請求介面 的例項
            GetRequest_Interface request = retrofit.create(GetRequest_Interface.class);

            // 步驟3:採用Observable<...>形式 對 2個網路請求 進行封裝
            observable1 = request.getCall().subscribeOn(Schedulers.io()); // 新開執行緒進行網路請求1
            observable2 = request.getCall_2().subscribeOn(Schedulers.io());// 新開執行緒進行網路請求2
            // 即2個網路請求非同步 & 同時傳送

            // 步驟4:通過使用Zip()對兩個網路請求進行合併再發送
            Observable.zip(observable1, observable2,
                    new BiFunction<Translation1, Translation2, String>() {
                        // 注:建立BiFunction物件傳入的第3個引數 = 合併後資料的資料型別
                        @Override
                        public String apply(Translation1 translation1,
                                            Translation2 translation2) throws Exception {
                            return translation1.show() + " & " +translation2.show();
                        }
                    }).observeOn(AndroidSchedulers.mainThread()) // 在主執行緒接收 & 處理資料
                    .subscribe(new Consumer<String>() {
                        // 成功返回資料時呼叫
                        @Override
                        public void accept(String combine_infro) throws Exception {
                            // 結合顯示2個網路請求的資料結果
                            Log.d(TAG, "最終接收到的資料是:" + combine_infro);
                        }
                    }, new Consumer<Throwable>() {
                        // 網路請求錯誤時呼叫
                        @Override
                        public void accept(Throwable throwable) throws Exception {
                            System.out.println("登入失敗");
                        }
                    });
        }
}

  • 測試結果

china不翻譯改為welcome