前言
Rxjava
,由於其基於事件流的鏈式調用、邏輯簡潔 & 使用簡單的特點,深受各大Android
開發者的歡迎。
Github截圖
如果還不瞭解RxJava,請看文章:Android:這是一篇 清晰 & 易懂的Rxjava 入門教程
RxJava
如此受歡迎的原因,在於其提供了豐富 & 功能強大的操作符,幾乎能完成所有的功能需求- 今天,我將爲大家帶來
Rxjava
創建操作符的實際開發需求場景:網絡請求嵌套回調 需求 ,並結合Retrofit
與RxJava
實現,希望大家會喜歡。
- 本系列文章主要基於
Rxjava 2.0
- 接下來的時間,我將持續推出
Android
中Rxjava 2.0
的一系列文章,包括原理、操作符、應用場景、背壓等等 ,有興趣可以繼續關注Carson_Ho的安卓開發筆記!!
示意圖
目錄
示意圖
1. 需求場景
1.1 背景
需要進行嵌套網絡請求:即在第1個網絡請求成功後,繼續再進行一次網絡請求
如 先進行 用戶註冊 的網絡請求, 待註冊成功後回再繼續發送 用戶登錄 的網絡請求
1.2 衝突
嵌套實現網絡請求較爲複雜,即嵌套調用函數
下面展示的是結合
Retrofit
與RxJava
的基本用法,即未用操作符前
// 發送註冊網絡請求的函數方法
private void register() {
api.register(new RegisterRequest())
.subscribeOn(Schedulers.io()) //在IO線程進行網絡請求
.observeOn(AndroidSchedulers.mainThread()) //回到主線程去處理請求結果
.subscribe(new Consumer<RegisterResponse>() {
@Override
public void accept(RegisterResponse registerResponse) throws Exception {
Toast.makeText(MainActivity.this, "註冊成功", Toast.LENGTH_SHORT).show();
login(); //註冊成功, 調用登錄的方法
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
Toast.makeText(MainActivity.this, "註冊失敗", Toast.LENGTH_SHORT).show();
}
});
}
// 發送登錄網絡請求的函數方法
private void login() {
api.login(new LoginRequest())
.subscribeOn(Schedulers.io()) //在IO線程進行網絡請求
.observeOn(AndroidSchedulers.mainThread()) //回到主線程去處理請求結果
.subscribe(new Consumer<LoginResponse>() {
@Override
public void accept(LoginResponse loginResponse) throws Exception {
Toast.makeText(MainActivity.this, "登錄成功", Toast.LENGTH_SHORT).show();
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
Toast.makeText(MainActivity.this, "登錄失敗", Toast.LENGTH_SHORT).show();
}
});
}
1.3 解決方案
結合 RxJava2
中的變換操作符FlatMap()
實現嵌套網絡請求
關於該操作符的使用具體請看文章:Android RxJava:圖文詳解 變換操作符
2. 功能說明
- 實現功能:發送嵌套網絡請求(將英文翻譯成中文,翻譯兩次)
- 爲了讓大家都能完成
Demo
,所以通過 公共的金山詞霸API 來模擬 “註冊 - 登錄”嵌套網絡請求- 即先翻譯
Register
(註冊),再翻譯Login
(登錄)
- 實現方案:採用
Get
方法對 金山詞霸API 發送網絡請求
採用
Gson
進行數據解析
金山詞典
3. 具體實現
下面我將結合 Retrofit
與RxJava
實現網絡請求嵌套
3.1 步驟說明
- 添加依賴
- 創建 接收服務器返回數據 的類
- 創建 用於描述網絡請求 的接口(區別於
Retrofit
傳統形式) - 創建 Retrofit 實例
- 創建 網絡請求接口實例 並 配置網絡請求參數(區別於
Retrofit
傳統形式) - 發送網絡請求(區別於
Retrofit
傳統形式) - 發送網絡請求
- 對返回的數據進行處理
本實例側重於說明
RxJava
的線程控制,關於Retrofit
的使用請看文章:這是一份很詳細的 Retrofit 2.0 使用教程(含實例講解)
3.2 步驟實現
步驟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格式說明
- 根據 金山詞霸API 的數據格式,創建 接收服務器返回數據 的類:
爲了演示是2個網絡請求,所以對應設置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 void show() {
Log.d("RxJava", "翻譯內容 = " + 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 void show() {
Log.d("RxJava", "翻譯內容 = " + content.out);
}
}
步驟3:創建 用於描述網絡請求 的接口
採用 註解 + Observable<...>
接口描述 網絡請求參數
GetRequest_Interface.java
public interface GetRequest_Interface {
// 網絡請求1
@GET("ajax.php?a=fy&f=auto&t=auto&w=hi%20register")
Observable<Translation1> getCall();
// 網絡請求2
@GET("ajax.php?a=fy&f=auto&t=auto&w=hi%20login")
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();
observable2 = request.getCall_2();
observable1.subscribeOn(Schedulers.io()) // (初始被觀察者)切換到IO線程進行網絡請求1
.observeOn(AndroidSchedulers.mainThread()) // (新觀察者)切換到主線程 處理網絡請求1的結果
.doOnNext(new Consumer<Translation1>() {
@Override
public void accept(Translation1 result) throws Exception {
Log.d(TAG, "第1次網絡請求成功");
result.show();
// 對第1次網絡請求返回的結果進行操作 = 顯示翻譯結果
}
})
.observeOn(Schedulers.io()) // (新被觀察者,同時也是新觀察者)切換到IO線程去發起登錄請求
// 特別注意:因爲flatMap是對初始被觀察者作變換,所以對於舊被觀察者,它是新觀察者,所以通過observeOn切換線程
// 但對於初始觀察者,它則是新的被觀察者
.flatMap(new Function<Translation1, ObservableSource<Translation2>>() { // 作變換,即作嵌套網絡請求
@Override
public ObservableSource<Translation2> apply(Translation1 result) throws Exception {
// 將網絡請求1轉換成網絡請求2,即發送網絡請求2
return observable2;
}
})
.observeOn(AndroidSchedulers.mainThread()) // (初始觀察者)切換到主線程 處理網絡請求2的結果
.subscribe(new Consumer<Translation2>() {
@Override
public void accept(Translation2 result) throws Exception {
Log.d(TAG, "第2次網絡請求成功");
result.show();
// 對第2次網絡請求返回的結果進行操作 = 顯示翻譯結果
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
System.out.println("登錄失敗");
}
});
}
}
3.3 測試結果
示意圖
4. Demo地址
Carson_Ho的Github地址 = RxJava2實戰系列:網絡請求嵌套回調
喜歡的麻煩點個
star
!
5. 總結
- 本文主要講解了
Rxjava
變換操作符的實際開發需求場景:嵌套回調需求 ,並結合Retrofit
與RxJava
實現 - 接下來的時間,我將持續推出
Android
中Rxjava 2.0
的一系列文章,包括原理、操作符、應用場景、背壓等等
示意圖
作者:Carson_Ho
鏈接:https://www.jianshu.com/p/5f5d61f04f96
來源:簡書
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。