1. 程式人生 > >Android:RxJava 結合 Retrofit 全面實現 網路請求出錯重連

Android:RxJava 結合 Retrofit 全面實現 網路請求出錯重連

前言

  • Rxjava,由於其基於事件流的鏈式呼叫、邏輯簡潔 & 使用簡單的特點,深受各大 Android開發者的歡迎。

Github截圖


  • RxJava如此受歡迎的原因,在於其提供了豐富 & 功能強大的操作符,幾乎能完成所有的功能需求
  • 今天,我將為大家帶來 Rxjava建立操作符的實際開發需求場景:網路請求出錯重連需求 ,並結合RetrofitRxJava 實現,希望大家會喜歡。
  1. 本系列文章主要基於 Rxjava 2.0
  2. 接下來的時間,我將持續推出 AndroidRxjava 2.0 的一系列文章,包括原理、操作符、應用場景、背壓等等 ,有興趣可以繼續關注
    Carson_Ho的安卓開發筆記
    !!

  3. 示意圖

目錄

示意圖

1. 需求場景

示意圖

2. 功能說明

  • 功能需求說明

示意圖

  • 功能邏輯

示意圖

  • 例項說明
    在本例子中:採用Get方法對 金山詞霸API 傳送網路請求
    1. 通過 斷開網路連線 模擬 網路異常錯誤(恢復網路即可成功傳送請求)
    2. 限制重試次數 = 10次
    3. 採用 Gson 進行資料解析

金山詞典

3. 具體實現

下面,我將結合 RetrofitRxJava 實現 網路請求出錯重連 功能

3.1 步驟說明

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

下面,將進行詳細的功能說明。

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 的資料格式,建立 接收伺服器返回資料 的類:

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:建立 用於描述網路請求 的介面

採用 註解 + 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:建立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<...>形式 對 網路請求 進行封裝
        Observable<Translation> observable = request.getCall();

        // 步驟4:傳送網路請求 & 通過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,  "發生異常 = "+ throwable.toString());

                        /**
                         * 需求1:根據異常型別選擇是否重試
                         * 即,當發生的異常 = 網路異常 = IO異常 才選擇重試
                         */
                        if (throwable instanceof IOException){

                            Log.d(TAG,  "屬於IO異常,需重試" );

                            /**
                             * 需求2:限制重試次數
                             * 即,當已重試次數 < 設定的重試次數,才選擇重試
                             */
                            if (currentRetryCount < maxConnectCount){

                                // 記錄重試次數
                                currentRetryCount++;
                                Log.d(TAG,  "重試次數 = " + currentRetryCount);

                                /**
                                 * 需求2:實現重試
                                 * 通過返回的Observable傳送的事件 = Next事件,從而使得retryWhen()重訂閱,最終實現重試功能
                                 *
                                 * 需求3:延遲1段時間再重試
                                 * 採用delay操作符 = 延遲一段時間傳送,以實現重試間隔設定
                                 *
                                 * 需求4:遇到的異常越多,時間越長
                                 * 在delay操作符的等待時間內設定 = 每重試1次,增多延遲重試時間1s
                                 */
                                // 設定等待時間
                                waitRetryTime = 1000 + currentRetryCount* 1000;
                                Log.d(TAG,  "等待時間 =" + waitRetryTime);
                                return Observable.just(1).delay(waitRetryTime, TimeUnit.MILLISECONDS);


                            }else{
                                // 若重試次數已 > 設定重試次數,則不重試
                                // 通過傳送error來停止重試(可在觀察者的onError()中獲取資訊)
                                return Observable.error(new Throwable("重試次數已超過設定次數 = " +currentRetryCount  + ",即 不再重試"));

                            }
                        }

                        // 若發生的異常不屬於I/O異常,則不重試
                        // 通過返回的Observable傳送的事件 = Error事件 實現(可在觀察者的onError()中獲取資訊)
                        else{
                            return Observable.error(new Throwable("發生了非網路異常(非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,  "傳送成功");
                        result.show();
                    }

                    @Override
                    public void onError(Throwable e) {
                        // 獲取停止重試的資訊
                        Log.d(TAG,  e.toString());
                    }

                    @Override
                    public void onComplete() {

                    }
                });

    }
}

3.3 測試結果

  1. 一開始先通過 斷開網路連線 模擬 網路異常錯誤,即開始重試;
  2. 等到第3次重試後恢復網路連線,即無發生網路異常錯誤,此時重試成功

示意圖

4. Demo地址

5. 總結

  • 本文主要講解了 Rxjava建立操作符的實際開發需求場景:網路請求出錯重連需求 ,並結合RetrofitRxJava 實現
  • 下面我將結合 實際場景應用 & Rxjava的相關使用框架(如RetrofitEventbus ,繼續對 AndroidRxjava 的實際開發需求場景進行深入講解 ,有興趣可以繼續關注Carson_Ho的安卓開發筆記

幫頂 / 評論點贊!因為你的鼓勵是我寫作的最大動力!

相關推薦

AndroidRxJava 結合 Retrofit 全面實現 網路請求出錯

前言 Rxjava,由於其基於事件流的鏈式呼叫、邏輯簡潔 & 使用簡單的特點,深受各大 Android開發者的歡迎。 RxJava如此受歡迎的原因,在於其提供了豐富 & 功能強大的操作符,幾乎能完成所有的功能需求 今天,我將為

AndroidRxJava 結合 Retrofit 優雅實現 網路請求輪詢

前言 Rxjava,由於其基於事件流的鏈式呼叫、邏輯簡潔 & 使用簡單的特點,深受各大 Android開發者的歡迎。 RxJava如此受歡迎的原因,在於其提供了豐富 & 功能強大的操作符,幾乎能完成所有的功能需求 今天,我將為

Android RxJava操作符的學習---功能性操作符--網路請求出錯結合Retrofit

1. 需求場景   2. 功能說明 功能需求說明     功能邏輯  例項說明 在本例子中:採用Get方法對 金山詞霸API 傳送網路請求 通過 斷開網路連線 模擬 網路異常錯誤(恢復網路即可

Android小知識-剖析Retrofit中的網路請求流程以及相關引數

本平臺的文章更新會有延遲,大家可以關注微信公眾號-顧林海,包括年底前會更新kotlin由淺入深系列教程,目前計劃在微信公眾號進行首發,如果大家想獲取最新教程,請關注微信公眾號,謝謝! 在使用Retrofit時,需要建立Retrofit的例項,定義一個網路請求介面併為介面中的方法添加註解,接著通過動

Android RxJava 實戰系列優雅實現 網路請求巢狀回撥

轉自-----http://blog.csdn.net/carson_ho/article/details/78315696,請為大神打call 前言 Rxjava,由於其基於事件流的鏈式呼叫、邏輯簡潔 & 使用簡單的特點,深受各大 Android

Android RxJava 實戰講解優雅實現 網路請求輪詢

轉自-----http://blog.csdn.net/carson_ho/article/details/78256466 前言 Rxjava,由於其基於事件流的鏈式呼叫、邏輯簡潔 & 使用簡單的特點,深受各大 Android開發者的歡迎。

Retrofit + Rxjava + RxAndroid實現網路請求

之前自己實現了一個新聞類閱讀APP,最近想使用當下流行的Retrofit + Rxjava + RxAndroid + MVP架構來重構一下,本文以每日一文作為資料來源API做一個簡單的示例,來介紹一下如何使用Retrofit + Rxjava + RxAndr

Android--menu和OkHttp框架(未封裝),結合Executors(執行緒池)實現網路請求的案例

涉及到的 知識點: 1.安卓UI元件menu 2.OkHttp框架 3.Executors(執行緒池) OkHttp結構簡介 案例程式碼 import android.os.Bundle; import android.suppo

AndroidRxJava的使用

說明: RxJava用於非同步執行任務,跟建立子執行緒執行任務無本質區別,優點在於讓程式碼看起來整潔優雅些,並不能減少程式碼量 一、加入jar包依賴(app下的build.gradle): dependencies { ... compile 'i

android使用small一步步實現外掛化與熱更新

由於外掛化開發與熱更新最近貌似越來越火,新開的專案準備也使用外掛化進行開發!其中遇到不少坑,在這裡寫了一個小的例子,記錄一下開發流程,有助於自己,同時希望能夠幫助大家理解,並且對於自身專案接入外掛化有所幫助! 外掛化 效果: 外掛化開發的含義:

RxJava+Retrofit2+MVP實現網路請求

上一遍部落格介紹了RxJava+Retrofit2的使用。在前段時間,刷招聘簡歷的時候,發現有一部分的公司會要求MVP模式的理解和具體使用。在現在越來越複雜的業務,我們的Activity的負擔也是越來越大,因此接著這篇我結合MVP模式來介紹一下自己對RxJava

RxJava結合Retrofit如何避免覆蓋http請求(終端當前http請求

unSubscribe("goodsListSubscribe");//取消前一次的http請求,避免頻繁請求導致響應次序及資料混亂 Subscription subscribe = goodsDAL.queryGoodsList(firstCategoryId, s

Android使用HttpUrlConnection來實現網路請求,親測有效

產品提出需求,需要再視訊播放完畢後把當前的播放位置上傳給伺服器。作為一名不愛造輪子的程式設計師,我果斷的使用了三方的視屏播放器,以module依賴的形式匯入到了工程,也由此產生了一個問題,三方module沒有Application的,也就無法進行整合OkGo來進行簡單的網路請

Android開發,使用Retrofit發送HTTP請求

service fin tps protect convert exceptio code find content 在build.gradle(Module: app)中加入 dependencies { ... implementation ‘com.

Swift使用Alamofire實現網路請求

  Alamofire是一個用Swift編寫的HTTP網路庫,由此前熱門開源專案AFNetworking的的作者mattt開發,可非常簡單地用於非同步網路通訊。 要獲取最新版本的 Alamofire,前往https://github.com/Alamofire/Alamofire然後單擊網頁右邊

OKHTTP-RecyclerView實現網路請求資料

build.gradle中匯入需要依賴 implementation ‘com.google.code.gson:gson:2.8.5’ implementation ‘com.android.support:design:27.1.1’ compile ‘cn.yipianfengye

android快取框架ASimpleCache的使用 (網路請求資料並快取)

官方簡介: ASimpleCache 是一個為Android制定的 輕量級的 開源快取框架。輕量到只有一個java檔案(由十幾個類精簡而來)。 框架地址 1、它可以快取什麼東西? 普通的字串、JsonObject、JsonArray、Bitmap、Drawable、

解析Node.js通過axios實現網路請求

本次給大家分享一篇node.js通過axios實現網路請求的方法,寫的十分的全面細緻,具有一定的參考價值,對此有需要的朋友可以參考學習下。如有不足之處,歡迎批評指正。 1、使用Npm 下載axios npm install --save axios var update_u

iOS NSURLSession 實現網路請求-檔案下載-上傳-後臺下載

 *  會話NSURLSession     NSURLConnection通過全域性狀態來管理cookies, 認證資訊等公共資源, 如果兩個連線需要使用不同的資源配置情況時就無法解決,     這個問題在NSURLSession可以解決, NSURLSession同

[Swift通天遁地]四、網路和執行緒-(4)使用Alamofire實現網路請求

本文將演示如何使用第三方庫實現網路請求服務。 首先確保在專案中已經安裝了所需的第三方庫。 點選【Podfile】,檢視安裝配置檔案。 1 source 'https://github.com/CocoaPods/Specs.git' 2 platform :ios, '12.0' 3 use_