前言
Rxjava
嗦锐,由于其基于事件流的鏈式調用沉御、邏輯簡潔 & 使用簡單的特點,深受各大 Android
開發(fā)者的歡迎皂冰。
如果還不了解RxJava,請看文章:Android:這是一篇 清晰 & 易懂的Rxjava 入門教程
-
RxJava
如此受歡迎的原因啊犬,在于其提供了豐富 & 功能強大的操作符灼擂,幾乎能完成所有的功能需求 - 今天,我將為大家?guī)?
Rxjava
創(chuàng)建操作符的實際開發(fā)需求場景:網絡請求出錯重連需求 觉至,并結合Retrofit
與RxJava
實現剔应,希望大家會喜歡。
Carson帶你學RxJava系列文章语御,包括 原理峻贮、操作符、應用場景应闯、背壓等等纤控,請關注看文章:Android:這是一份全面 & 詳細的RxJava學習指南
目錄
1. 需求場景
2. 功能說明
- 功能需求說明
注:關于
Rxjava
中的retryWhen()
操作符的使用請看文章Android RxJava:功能性操作符 全面講解
- 功能邏輯
- 實例說明
在本例子中:采用Get
方法對 金山詞霸API 發(fā)送網絡請求- 通過 斷開網絡連接 模擬 網絡異常錯誤(恢復網絡即可成功發(fā)送請求)
- 限制重試次數 = 10次
- 采用
Gson
進行數據解析
3. 具體實現
下面,我將結合 Retrofit
與RxJava
實現 網絡請求出錯重連 功能
3.1 步驟說明
- 添加依賴
- 創(chuàng)建 接收服務器返回數據 的類
- 創(chuàng)建 用于描述網絡請求 的接口(區(qū)別于
Retrofit
傳統形式) - 創(chuàng)建
Retrofit
實例 - 創(chuàng)建 網絡請求接口實例 并 配置網絡請求參數(區(qū)別于
Retrofit
傳統形式) - 發(fā)送網絡請求(區(qū)別于
Retrofit
傳統形式) - 發(fā)送網絡請求
- 對返回的數據進行處理
下面碉纺,將進行詳細的功能說明船万。
本實例側重于說明
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:創(chuàng)建 接收服務器返回數據 的類
- 金山詞霸
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 的數據格式婚瓜,創(chuàng)建 接收服務器返回數據 的類:
Translation.java
public class Translation {
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:創(chuàng)建 用于描述網絡請求 的接口
采用 注解 + Observable<...>
接口描述 網絡請求參數
GetRequest_Interface.java
public interface GetRequest_Interface {
@GET("ajax.php?a=fy&f=auto&t=auto&w=hi%20world")
Observable<Translation> getCall();
// 注解里傳入 網絡請求 的部分URL地址
// Retrofit把網絡請求的URL分成了兩部分:一部分放在Retrofit對象里,另一部分放在網絡請求接口里
// 如果接口里的url是一個完整的網址刑棵,那么放在Retrofit對象里的URL可以忽略
// 采用Observable<...>接口
// getCall()是接受網絡請求數據的方法
}
接下來的步驟均在RxJavafixRxjava.java內實現(請看注釋)
RxJavafixRxjava.java
public class RxJavafixRetrofit2 extends AppCompatActivity {
private static final String TAG = "RxJava";
// 設置變量
// 可重試次數
private int maxConnectCount = 10;
// 當前已重試次數
private int currentRetryCount = 0;
// 重試等待時間
private int waitRetryTime = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 步驟1:創(chuàng)建Retrofit對象
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://fy.iciba.com/") // 設置 網絡請求 Url
.addConverterFactory(GsonConverterFactory.create()) //設置使用Gson解析(記得加入依賴)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 支持RxJava
.build();
// 步驟2:創(chuàng)建 網絡請求接口 的實例
GetRequest_Interface request = retrofit.create(GetRequest_Interface.class);
// 步驟3:采用Observable<...>形式 對 網絡請求 進行封裝
Observable<Translation> observable = request.getCall();
// 步驟4:發(fā)送網絡請求 & 通過retryWhen()進行重試
// 注:主要異常才會回調retryWhen()進行重試
observable.retryWhen(new Function<Observable<Throwable>, ObservableSource<?>>() {
@Override
public ObservableSource<?> apply(@NonNull Observable<Throwable> throwableObservable) throws Exception {
// 參數Observable<Throwable>中的泛型 = 上游操作符拋出的異常巴刻,可通過該條件來判斷異常的類型
return throwableObservable.flatMap(new Function<Throwable, ObservableSource<?>>() {
@Override
public ObservableSource<?> apply(@NonNull Throwable throwable) throws Exception {
// 輸出異常信息
Log.d(TAG, "發(fā)生異常 = "+ throwable.toString());
/**
* 需求1:根據異常類型選擇是否重試
* 即,當發(fā)生的異常 = 網絡異常 = IO異常 才選擇重試
*/
if (throwable instanceof IOException){
Log.d(TAG, "屬于IO異常蛉签,需重試" );
/**
* 需求2:限制重試次數
* 即胡陪,當已重試次數 < 設置的重試次數,才選擇重試
*/
if (currentRetryCount < maxConnectCount){
// 記錄重試次數
currentRetryCount++;
Log.d(TAG, "重試次數 = " + currentRetryCount);
/**
* 需求2:實現重試
* 通過返回的Observable發(fā)送的事件 = Next事件碍舍,從而使得retryWhen()重訂閱柠座,最終實現重試功能
*
* 需求3:延遲1段時間再重試
* 采用delay操作符 = 延遲一段時間發(fā)送,以實現重試間隔設置
*
* 需求4:遇到的異常越多片橡,時間越長
* 在delay操作符的等待時間內設置 = 每重試1次妈经,增多延遲重試時間1s
*/
// 設置等待時間
waitRetryTime = 1000 + currentRetryCount* 1000;
Log.d(TAG, "等待時間 =" + waitRetryTime);
return Observable.just(1).delay(waitRetryTime, TimeUnit.MILLISECONDS);
}else{
// 若重試次數已 > 設置重試次數,則不重試
// 通過發(fā)送error來停止重試(可在觀察者的onError()中獲取信息)
return Observable.error(new Throwable("重試次數已超過設置次數 = " +currentRetryCount + "捧书,即 不再重試"));
}
}
// 若發(fā)生的異常不屬于I/O異常吹泡,則不重試
// 通過返回的Observable發(fā)送的事件 = Error事件 實現(可在觀察者的onError()中獲取信息)
else{
return Observable.error(new Throwable("發(fā)生了非網絡異常(非I/O異常)"));
}
}
});
}
}).subscribeOn(Schedulers.io()) // 切換到IO線程進行網絡請求
.observeOn(AndroidSchedulers.mainThread()) // 切換回到主線程 處理請求結果
.subscribe(new Observer<Translation>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Translation result) {
// 接收服務器返回的數據
Log.d(TAG, "發(fā)送成功");
result.show();
}
@Override
public void onError(Throwable e) {
// 獲取停止重試的信息
Log.d(TAG, e.toString());
}
@Override
public void onComplete() {
}
});
}
}
3.3 測試結果
- 一開始先通過 斷開網絡連接 模擬 網絡異常錯誤,即開始重試经瓷;
- 等到第3次重試后恢復網絡連接爆哑,即無發(fā)生網絡異常錯誤,此時重試成功
4. Demo地址
Carson_Ho的Github地址 = RxJava2實戰(zhàn)系列:出錯重連
5. 總結
- 本文主要講解了
Rxjava
創(chuàng)建操作符的實際開發(fā)需求場景:網絡請求出錯重連需求 舆吮,并結合Retrofit
與RxJava
實現 - Carson帶你學RxJava系列文章:
入門
Carson帶你學Android:這是一篇清晰易懂的Rxjava入門教程
Carson帶你學Android:面向初學者的RxJava使用指南
Carson帶你學Android:RxJava2.0到底更新了什么揭朝?
原理
Carson帶你學Android:圖文解析RxJava原理
Carson帶你學Android:手把手帶你源碼分析RxJava
使用教程:操作符
Carson帶你學Android:RxJava操作符教程
Carson帶你學Android:RxJava創(chuàng)建操作符
Carson帶你學Android:RxJava功能性操作符
Carson帶你學Android:RxJava過濾操作符
Carson帶你學Android:RxJava組合/合并操作符
Carson帶你學Android:RxJava變換操作符
Carson帶你學Android:RxJava條件/布爾操作符
實戰(zhàn)
Carson帶你學Android:什么時候應該使用Rxjava队贱?(開發(fā)場景匯總)
Carson帶你學Android:RxJava線程控制(含實例講解)
Carson帶你學Android:圖文詳解RxJava背壓策略
Carson帶你學Android:RxJava、Retrofit聯合使用匯總(含實例教程)
Carson帶你學Android:優(yōu)雅實現網絡請求嵌套回調
Carson帶你學Android:網絡請求輪詢(有條件)
Carson帶你學Android:網絡請求輪詢(無條件)
Carson帶你學Android:網絡請求出錯重連(結合Retrofit)
Carson帶你學Android:合并數據源
Carson帶你學Android:聯想搜索優(yōu)化
Carson帶你學Android:功能防抖
Carson帶你學Android:從磁盤/內存緩存中獲取緩存數據
Carson帶你學Android:聯合判斷
歡迎關注Carson_Ho的簡書
不定期分享關于安卓開發(fā)的干貨潭袱,追求短露筒、平、快敌卓,但卻不缺深度慎式。