1. 程式人生 > >Android:Retrofit 與 RxJava聯合使用大合集(含例項教程)!

Android:Retrofit 與 RxJava聯合使用大合集(含例項教程)!

前言

  • Andrroid開發中,網路請求十分常用,而在Android網路請求庫中,Retrofit是當下最熱的一個網路請求庫

Github截圖

  • Retrofit之所以作為現在最流行的網路請求庫,其中一個主要原因是:支援RxJavaRxjava由於其基於事件流的鏈式呼叫、邏輯簡潔 & 使用簡單的特點,深受各大 Android開發者的歡迎。

Github截圖


  • 今天,我將為大家帶來 Retrofit 結合Rxjava實際應用案例教學,即常見開發應用場景實現 ,希望大家會喜歡。

本文主要基於Retrofit 2.0 & Rxjava 2.0
1. 本系列文章主要基於 Rxjava 2.0


2. 接下來的時間,我將持續推出 AndroidRxjava 2.0 的一系列文章,包括原理、操作符、應用場景、背壓等等 ,有興趣可以繼續關注Carson_Ho的安卓開發筆記!!

示意圖

目錄

示意圖

1. Retrofit 簡介

示意圖

特別注意:

  • 準確來說,Retrofit 是一個 RESTful 的 HTTP 網路請求框架的封裝。
  • 原因:網路請求的工作本質上是 OkHttp 完成,而 Retrofit 僅負責 網路請求介面的封裝

2. RxJava簡介

示意圖

3. 二者結合使用

  • Retrofit之所以作為現在最流行的網路請求庫,其中一個主要原因是:支援RxJava

    即:Retrofit除了提供傳統的網路請求方式外,還提供 RxJava 版本的 網路請求方式
  • 兩種方式在使用上最大的區別在於:傳統方式採用了 Callback 介面,而RxJava 方式則採用了Observable介面。主要體現在:
    1. 用於描述網路請求 的介面 的設定
    2. 網路請求的封裝形式 & 傳送形式

a. 用於描述網路請求 的介面設定

// 傳統方式:Call<..>介面形式
public interface GetRequest_Interface {
 @GET("url地址")
    Call<Translation> getCall();
    // 註解裡傳入 網路請求 的部分URL地址
// getCall()是接受網路請求資料的方法 } // RxJava 方式:Observable<..>介面形式 @GET("url地址") public interface GetRequest_Interface { Observable<Translation> getCall();

b. 網路請求的封裝形式 & 傳送形式不同

<-- 傳統方式 ->>
        // 1. 建立 網路請求介面 的例項
        GetRequest_Interface request = retrofit.create(GetRequest_Interface.class);

        // 2. 採用Call<..>介面 對 傳送請求 進行封裝
        Call<Translation> call = request.getCall();

        // 3. 傳送網路請求(非同步)
        call.enqueue(new Callback<Translation>() {
            // 請求成功時回撥
            @Override
            public void onResponse(Call<Translation> call, Response<Translation> response) {
                 ...  
            }

            // 請求失敗時回撥
            @Override
            public void onFailure(Call<Translation> call, Throwable throwable) {
                ....
            }
        });


<-- RxJava 版方式 ->>
        // 1. 建立 網路請求介面 的例項
        GetRequest_Interface request = retrofit.create(GetRequest_Interface.class);

        // 2. 採用Observable<...>形式 對 網路請求 進行封裝
        Observable<Translation> observable = request.getCall();

        // 3. 傳送網路請求(非同步)
        observable.subscribeOn(Schedulers.io())               // 在IO執行緒進行網路請求
                  .observeOn(AndroidSchedulers.mainThread())  // 回到主執行緒 處理請求結果
                  .subscribe(new Observer<Translation>() {

                    // 傳送請求後呼叫該複寫方法(無論請求成功與否)
                    @Override
                    public void onSubscribe(Disposable d) {
                        ...// 初始化工作
                      }

                    // 傳送請求成功後呼叫該複寫方法
                    @Override
                    public void onNext(Translation result) {
                        ...// 對返回結果Translation類物件 進行處理
                    }

                    // 傳送請求成功後,先呼叫onNext()再呼叫該複寫方法
                    @Override
                    public void onComplete() {
                        Log.d(TAG, "請求成功");
                    }
                    // 傳送請求失敗後呼叫該複寫方法
                    @Override
                    public void onError(Throwable e) {
                        Log.d(TAG, "請求失敗");
                    }

                });
    }

4. 基礎使用

下面,我將採用最基礎的 `Retrofit + RxJava` 實現 網路請求 的功能

4.1 功能說明

  • 實現功能:將中文翻譯成英文 - > 顯示到介面
  • 實現方案:採用Get方法對 金山詞霸API 傳送網路請求
    1. 先切換到工作執行緒 傳送網路請求
    2. 再切換到主執行緒進行 UI更新

金山詞典

4.2 步驟說明

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

4.3 步驟實現

步驟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() {
        System.out.println( "Rxjava翻譯結果:" + status);
        System.out.println("Rxjava翻譯結果:" + content.from);
        System.out.println("Rxjava翻譯結果:" + content.to);
        System.out.println("Rxjava翻譯結果:" + content.vendor);
        System.out.println("Rxjava翻譯結果:" + content.out);
        System.out.println("Rxjava翻譯結果:" + content.errNo);
    }
}
步驟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()是接受網路請求資料的方法
}
接下來的步驟均在MainActivity.java內實現(請看註釋)

MainActivity.java

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "Rxjava";

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

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

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

        // 步驟6:採用Observable<...>形式 對 網路請求 進行封裝
        Observable<Translation> observable = request.getCall();

        // 步驟7:傳送網路請求
        observable.subscribeOn(Schedulers.io())               // 在IO執行緒進行網路請求
                  .observeOn(AndroidSchedulers.mainThread())  // 回到主執行緒 處理請求結果
                  .subscribe(new Observer<Translation>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        Log.d(TAG, "開始採用subscribe連線");
                    }

                    @Override
                    public void onNext(Translation result) {
                        // 步驟8:對返回的資料進行處理
                        result.show() ;
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.d(TAG, "請求失敗");
                    }

                    @Override
                    public void onComplete() {
                        Log.d(TAG, "請求成功");
                    }
                });
    }
}

4.4 測試結果

示意圖

4.5 Demo地址

5. 實際開發需求案例

  • 下面,我將使用Retrofit & RxJava,並結合實際的開發需求場景進行案例的講解
  • 講解的實際開發需求場景包括:

示意圖

5.1 網路請求輪詢(無條件)

  • 需求場景說明

示意圖

5.2 網路請求輪詢(有條件)

  • 需求場景

示意圖

5.3 網路請求巢狀回撥

  • 背景
    需要進行巢狀網路請求:即在第1個網路請求成功後,繼續再進行一次網路請求

    如 先進行 使用者註冊 的網路請求, 待註冊成功後回再繼續傳送 使用者登入 的網路請求

  • 衝突
    巢狀實現網路請求較為複雜,即巢狀呼叫函式

    下面展示的是結合 RetrofitRxJava的基本用法,即未用操作符前

// 傳送註冊網路請求的函式方法
    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();
                    }
                });
    }
  • 解決方案
    結合 RxJava2中的變換操作符FlatMap()實現巢狀網路請求

5.4 網路請求出錯重連

  • 需求場景
    示意圖

  • 功能需求說明

示意圖

  • 功能邏輯

示意圖

5.5 合併資料來源 & 統一顯示

  • 需求場景

示意圖

  • 功能說明
    即,同時向2個伺服器傳送網路請求 ->> 獲取資料 ->> 合併資料 ->> 統一展示到客戶端

至此,關於Retrofit & RxJava的實際開發需求場景講解完畢。

6. Demo地址

7. 總結

  • 本文主要講解了Retrofit & RxJava的結合使用 & 實際開發需求實現
  • 下面,我將繼續深入講解 Rxjava 的其他實際開發需求場景 (結合相關框架,如RxBindingEventbus),有興趣可以繼續關注Carson_Ho的安卓開發筆記

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