Android RxJava操作符的學習---組合合併操作符---合併資料來源並展示
阿新 • • 發佈:2018-11-09
1. 需求場景
2. 功能說明
即,同時向2個數據源獲取資料 -> 合併資料 -> 統一展示到客戶端
3. 具體實現
此處採用Merge()
& Zip()
操作符進行講解,其中:
Merge()
例子 :實現較為簡單的從(網路 + 本地)獲取資料 & 統一展示Zip()
例子:結合Retrofit
與RxJava
,實現較為複雜的合併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()操作符
-
功能說明
在該例中,我將結合結合Retrofit
與RxJava
,實現:- 從不同資料來源(2個伺服器)獲取資料,即 合併網路請求的傳送
- 統一顯示結果
-
實現方案
採用Get
方法 對 金山詞霸API
傳送2個網路請求(將英文翻譯成中文,翻譯2次) & 將2次翻譯的結果一起顯示。
採用
Gson
進行資料解析
步驟說明
- 新增依賴
- 建立 接收伺服器返回資料 的類
- 建立 用於描述網路請求 的介面
- 建立 Retrofit 例項
- 建立 網路請求介面例項 並 配置網路請求引數
- 傳送網路請求
- 傳送網路請求
- 對返回的資料進行處理
- 步驟實現
步驟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