Carson帶你學(xué)Android:RxJava、Retrofit聯(lián)合使用匯總(含實(shí)例教程)


前言

  • Andrroid開發(fā)中,網(wǎng)絡(luò)請(qǐng)求十分常用,而在Android網(wǎng)絡(luò)請(qǐng)求庫中,Retrofit是當(dāng)下最熱的一個(gè)網(wǎng)絡(luò)請(qǐng)求庫
  • Retrofit之所以作為現(xiàn)在最流行的網(wǎng)絡(luò)請(qǐng)求庫,其中一個(gè)主要原因是:支持RxJava。Rxjava由于其基于事件流的鏈?zhǔn)秸{(diào)用、邏輯簡潔 & 使用簡單的特點(diǎn),深受各大 Android開發(fā)者的歡迎。
  • 今天,我將為大家?guī)?Retrofit 結(jié)合Rxjava實(shí)際應(yīng)用案例教學(xué),即常見開發(fā)應(yīng)用場景實(shí)現(xiàn) ,希望大家會(huì)喜歡。

Carson帶你學(xué)RxJava系列文章,包括 原理、操作符、應(yīng)用場景、背壓等等,請(qǐng)關(guān)注看文章:Android:這是一份全面 & 詳細(xì)的RxJava學(xué)習(xí)指南


目錄

示意圖

1. Retrofit 簡介

示意圖

特別注意:

  • 準(zhǔn)確來說,Retrofit 是一個(gè) RESTful 的 HTTP 網(wǎng)絡(luò)請(qǐng)求框架的封裝。
  • 原因:網(wǎng)絡(luò)請(qǐng)求的工作本質(zhì)上是 OkHttp 完成,而 Retrofit 僅負(fù)責(zé) 網(wǎng)絡(luò)請(qǐng)求接口的封裝

關(guān)于Retrofit的更加詳細(xì)介紹請(qǐng)看文章:這是一份很詳細(xì)的 Retrofit 2.0 使用教程(含實(shí)例講解)


2. RxJava簡介

示意圖

關(guān)于RxJava的更加詳細(xì)介紹請(qǐng)看文章:Android Rxjava:這是一篇 清晰 & 易懂的Rxjava 入門教程


3. 二者結(jié)合使用

  • Retrofit之所以作為現(xiàn)在最流行的網(wǎng)絡(luò)請(qǐng)求庫,其中一個(gè)主要原因是:支持RxJava

即:Retrofit除了提供傳統(tǒng)的網(wǎng)絡(luò)請(qǐng)求方式外,還提供 RxJava 版本的 網(wǎng)絡(luò)請(qǐng)求方式

  • 兩種方式在使用上最大的區(qū)別在于:傳統(tǒng)方式采用了 Callback 接口,而RxJava 方式則采用了Observable接口。主要體現(xiàn)在:
    1. 用于描述網(wǎng)絡(luò)請(qǐng)求 的接口 的設(shè)置
    2. 網(wǎng)絡(luò)請(qǐng)求的封裝形式 & 發(fā)送形式

a. 用于描述網(wǎng)絡(luò)請(qǐng)求 的接口設(shè)置

// 傳統(tǒng)方式:Call<..>接口形式
public interface GetRequest_Interface {
 @GET("url地址")
    Call<Translation> getCall();
    // 注解里傳入 網(wǎng)絡(luò)請(qǐng)求 的部分URL地址
    // getCall()是接受網(wǎng)絡(luò)請(qǐng)求數(shù)據(jù)的方法
}

//  RxJava 方式:Observable<..>接口形式
 @GET("url地址")
public interface GetRequest_Interface {
Observable<Translation> getCall();

b. 網(wǎng)絡(luò)請(qǐng)求的封裝形式 & 發(fā)送形式不同

<-- 傳統(tǒng)方式 ->>
        // 1. 創(chuàng)建 網(wǎng)絡(luò)請(qǐng)求接口 的實(shí)例
        GetRequest_Interface request = retrofit.create(GetRequest_Interface.class);

        // 2. 采用Call<..>接口 對(duì) 發(fā)送請(qǐng)求 進(jìn)行封裝
        Call<Translation> call = request.getCall();

        // 3. 發(fā)送網(wǎng)絡(luò)請(qǐng)求(異步)
        call.enqueue(new Callback<Translation>() {
            // 請(qǐng)求成功時(shí)回調(diào)
            @Override
            public void onResponse(Call<Translation> call, Response<Translation> response) {
                 ...  
            }

            // 請(qǐng)求失敗時(shí)回調(diào)
            @Override
            public void onFailure(Call<Translation> call, Throwable throwable) {
                ....
            }
        });


<-- RxJava 版方式 ->>
        // 1. 創(chuàng)建 網(wǎng)絡(luò)請(qǐng)求接口 的實(shí)例
        GetRequest_Interface request = retrofit.create(GetRequest_Interface.class);

        // 2. 采用Observable<...>形式 對(duì) 網(wǎng)絡(luò)請(qǐng)求 進(jìn)行封裝
        Observable<Translation> observable = request.getCall();
        
        // 3. 發(fā)送網(wǎng)絡(luò)請(qǐng)求(異步)
        observable.subscribeOn(Schedulers.io())               // 在IO線程進(jìn)行網(wǎng)絡(luò)請(qǐng)求
                  .observeOn(AndroidSchedulers.mainThread())  // 回到主線程 處理請(qǐng)求結(jié)果
                  .subscribe(new Observer<Translation>() {

                    // 發(fā)送請(qǐng)求后調(diào)用該復(fù)寫方法(無論請(qǐng)求成功與否)
                    @Override
                    public void onSubscribe(Disposable d) {
                        ...// 初始化工作
                      }
                    
                    // 發(fā)送請(qǐng)求成功后調(diào)用該復(fù)寫方法
                    @Override
                    public void onNext(Translation result) {
                        ...// 對(duì)返回結(jié)果Translation類對(duì)象 進(jìn)行處理
                    }

                    // 發(fā)送請(qǐng)求成功后,先調(diào)用onNext()再調(diào)用該復(fù)寫方法
                    @Override
                    public void onComplete() {
                        Log.d(TAG, "請(qǐng)求成功");
                    }
                    // 發(fā)送請(qǐng)求失敗后調(diào)用該復(fù)寫方法
                    @Override
                    public void onError(Throwable e) {
                        Log.d(TAG, "請(qǐng)求失敗");
                    }

                });
    }


4. 基礎(chǔ)使用

下面,我將采用最基礎(chǔ)的 Retrofit + RxJava 實(shí)現(xiàn) 網(wǎng)絡(luò)請(qǐng)求 的功能

4.1 功能說明

  • 實(shí)現(xiàn)功能:將中文翻譯成英文 - > 顯示到界面
  • 實(shí)現(xiàn)方案:采用Get方法對(duì) 金山詞霸API 發(fā)送網(wǎng)絡(luò)請(qǐng)求
  1. 先切換到工作線程 發(fā)送網(wǎng)絡(luò)請(qǐng)求
  2. 再切換到主線程進(jìn)行 UI更新
金山詞典

4.2 步驟說明

  1. 添加依賴
  2. 創(chuàng)建 接收服務(wù)器返回?cái)?shù)據(jù) 的類
  3. 創(chuàng)建 用于描述網(wǎng)絡(luò)請(qǐng)求 的接口(區(qū)別于傳統(tǒng)形式)
  4. 創(chuàng)建 Retrofit 實(shí)例
  5. 創(chuàng)建 網(wǎng)絡(luò)請(qǐng)求接口實(shí)例 并 配置網(wǎng)絡(luò)請(qǐng)求參數(shù)(區(qū)別于傳統(tǒng)形式)
  6. 發(fā)送網(wǎng)絡(luò)請(qǐng)求(區(qū)別于傳統(tǒng)形式)
  7. 發(fā)送網(wǎng)絡(luò)請(qǐng)求
  8. 對(duì)返回的數(shù)據(jù)進(jìn)行處理

本實(shí)例側(cè)重于說明 RxJava 的線程控制,關(guān)于Retrofit的使用請(qǐng)看文章:這是一份很詳細(xì)的 Retrofit 2.0 使用教程(含實(shí)例講解)

4.3 步驟實(shí)現(xiàn)

步驟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. 添加 網(wǎng)絡(luò)權(quán)限
AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET"/>
步驟2:創(chuàng)建 接收服務(wù)器返回?cái)?shù)據(jù) 的類
  • 金山詞霸API 的數(shù)據(jù)格式說明如下:
// URL模板
http://fy.iciba.com/ajax.php

// URL實(shí)例
http://fy.iciba.com/ajax.php?a=fy&f=auto&t=auto&w=hello%20world

// 參數(shù)說明:
// a:固定值 fy
// f:原文內(nèi)容類型,日語取 ja,中文取 zh,英語取 en,韓語取 ko,德語取 de,西班牙語取 es,法語取 fr,自動(dòng)則取 auto
// t:譯文內(nèi)容類型,日語取 ja,中文取 zh,英語取 en,韓語取 ko,德語取 de,西班牙語取 es,法語取 fr,自動(dòng)則取 auto
// w:查詢內(nèi)容
  • 示例
API格式說明
  • 根據(jù) 金山詞霸API 的數(shù)據(jù)格式,創(chuàng)建 接收服務(wù)器返回?cái)?shù)據(jù) 的類:

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;
    }

    //定義 輸出返回?cái)?shù)據(jù) 的方法
    public void show() {
        System.out.println( "Rxjava翻譯結(jié)果:" + status);
        System.out.println("Rxjava翻譯結(jié)果:" + content.from);
        System.out.println("Rxjava翻譯結(jié)果:" + content.to);
        System.out.println("Rxjava翻譯結(jié)果:" + content.vendor);
        System.out.println("Rxjava翻譯結(jié)果:" + content.out);
        System.out.println("Rxjava翻譯結(jié)果:" + content.errNo);
    }
}
步驟3:創(chuàng)建 用于描述網(wǎng)絡(luò)請(qǐng)求 的接口

采用 注解 + Observable<...>接口描述 網(wǎng)絡(luò)請(qǐng)求參數(shù)

GetRequest_Interface.java

public interface GetRequest_Interface {

    @GET("ajax.php?a=fy&f=auto&t=auto&w=hi%20world")
    Observable<Translation> getCall();
     // 注解里傳入 網(wǎng)絡(luò)請(qǐng)求 的部分URL地址
    // Retrofit把網(wǎng)絡(luò)請(qǐng)求的URL分成了兩部分:一部分放在Retrofit對(duì)象里,另一部分放在網(wǎng)絡(luò)請(qǐng)求接口里
    // 如果接口里的url是一個(gè)完整的網(wǎng)址,那么放在Retrofit對(duì)象里的URL可以忽略
    // 采用Observable<...>接口 
    // getCall()是接受網(wǎng)絡(luò)請(qǐng)求數(shù)據(jù)的方法
}
接下來的步驟均在MainActivity.java內(nèi)實(shí)現(xiàn)(請(qǐng)看注釋)

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:創(chuàng)建Retrofit對(duì)象
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://fy.iciba.com/") // 設(shè)置 網(wǎng)絡(luò)請(qǐng)求 Url
                .addConverterFactory(GsonConverterFactory.create()) //設(shè)置使用Gson解析(記得加入依賴)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 支持RxJava
                .build();

        // 步驟5:創(chuàng)建 網(wǎng)絡(luò)請(qǐng)求接口 的實(shí)例
        GetRequest_Interface request = retrofit.create(GetRequest_Interface.class);

        // 步驟6:采用Observable<...>形式 對(duì) 網(wǎng)絡(luò)請(qǐng)求 進(jìn)行封裝
        Observable<Translation> observable = request.getCall();

        // 步驟7:發(fā)送網(wǎng)絡(luò)請(qǐng)求
        observable.subscribeOn(Schedulers.io())               // 在IO線程進(jìn)行網(wǎng)絡(luò)請(qǐng)求
                  .observeOn(AndroidSchedulers.mainThread())  // 回到主線程 處理請(qǐng)求結(jié)果
                  .subscribe(new Observer<Translation>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        Log.d(TAG, "開始采用subscribe連接");
                    }

                    @Override
                    public void onNext(Translation result) {
                        // 步驟8:對(duì)返回的數(shù)據(jù)進(jìn)行處理
                        result.show() ;
                    }

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

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

4.4 測試結(jié)果

示意圖

4.5 Demo地址

Carson_Ho的Github地址 = Retrofit結(jié)合RxJava實(shí)戰(zhàn)系列:基礎(chǔ)使用


5. 實(shí)際開發(fā)需求案例

  • 下面,我將使用Retrofit & RxJava,并結(jié)合實(shí)際的開發(fā)需求場景進(jìn)行案例的講解
  • 講解的實(shí)際開發(fā)需求場景包括:
示意圖

5.1 網(wǎng)絡(luò)請(qǐng)求輪詢(無條件)

  • 需求場景說明
示意圖

5.2 網(wǎng)路請(qǐng)求輪詢(有條件)

  • 需求場景
示意圖

5.3 網(wǎng)絡(luò)請(qǐng)求嵌套回調(diào)

  • 背景
    需要進(jìn)行嵌套網(wǎng)絡(luò)請(qǐng)求:即在第1個(gè)網(wǎng)絡(luò)請(qǐng)求成功后,繼續(xù)再進(jìn)行一次網(wǎng)絡(luò)請(qǐng)求

如 先進(jìn)行 用戶注冊 的網(wǎng)絡(luò)請(qǐng)求, 待注冊成功后回再繼續(xù)發(fā)送 用戶登錄 的網(wǎng)絡(luò)請(qǐng)求

  • 沖突
    嵌套實(shí)現(xiàn)網(wǎng)絡(luò)請(qǐng)求較為復(fù)雜,即嵌套調(diào)用函數(shù)

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

// 發(fā)送注冊網(wǎng)絡(luò)請(qǐng)求的函數(shù)方法
    private void register() {
        api.register(new RegisterRequest())
                .subscribeOn(Schedulers.io())               //在IO線程進(jìn)行網(wǎng)絡(luò)請(qǐng)求
                .observeOn(AndroidSchedulers.mainThread())  //回到主線程去處理請(qǐng)求結(jié)果
                .subscribe(new Consumer<RegisterResponse>() {
                    @Override
                    public void accept(RegisterResponse registerResponse) throws Exception {
                        Toast.makeText(MainActivity.this, "注冊成功", Toast.LENGTH_SHORT).show();
                        login();   //注冊成功, 調(diào)用登錄的方法
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        Toast.makeText(MainActivity.this, "注冊失敗", Toast.LENGTH_SHORT).show();
                    }
                });
    }


// 發(fā)送登錄網(wǎng)絡(luò)請(qǐng)求的函數(shù)方法
private void login() {
        api.login(new LoginRequest())
                .subscribeOn(Schedulers.io())               //在IO線程進(jìn)行網(wǎng)絡(luò)請(qǐng)求
                .observeOn(AndroidSchedulers.mainThread())  //回到主線程去處理請(qǐng)求結(jié)果
                .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();
                    }
                });
    }


5.4 網(wǎng)絡(luò)請(qǐng)求出錯(cuò)重連

  • 需求場景


    示意圖
  • 功能需求說明

示意圖
  • 功能邏輯
示意圖

5.5 合并數(shù)據(jù)源 & 統(tǒng)一顯示

  • 需求場景
示意圖

至此,關(guān)于Retrofit & RxJava的實(shí)際開發(fā)需求場景講解完畢。


6. Demo地址

上述所有案例的源代碼都存放在:Carson_Ho的Github地址 = Retrofit結(jié)合RxJava實(shí)戰(zhàn)系列


7. 總結(jié)

  • 本文主要講解了Retrofit & RxJava的結(jié)合使用 & 實(shí)際開發(fā)需求實(shí)現(xiàn)
  • Carson帶你學(xué)RxJava系列文章:

入門
Carson帶你學(xué)Android:這是一篇清晰易懂的Rxjava入門教程
Carson帶你學(xué)Android:面向初學(xué)者的RxJava使用指南
Carson帶你學(xué)Android:RxJava2.0到底更新了什么?
原理
Carson帶你學(xué)Android:圖文解析RxJava原理
Carson帶你學(xué)Android:手把手帶你源碼分析RxJava
使用教程:操作符
Carson帶你學(xué)Android:RxJava操作符教程
Carson帶你學(xué)Android:RxJava創(chuàng)建操作符
Carson帶你學(xué)Android:RxJava功能性操作符
Carson帶你學(xué)Android:RxJava過濾操作符
Carson帶你學(xué)Android:RxJava組合/合并操作符
Carson帶你學(xué)Android:RxJava變換操作符
Carson帶你學(xué)Android:RxJava條件/布爾操作符
實(shí)戰(zhàn)
Carson帶你學(xué)Android:什么時(shí)候應(yīng)該使用Rxjava?(開發(fā)場景匯總)
Carson帶你學(xué)Android:RxJava線程控制(含實(shí)例講解)
Carson帶你學(xué)Android:圖文詳解RxJava背壓策略
Carson帶你學(xué)Android:RxJava、Retrofit聯(lián)合使用匯總(含實(shí)例教程)
Carson帶你學(xué)Android:優(yōu)雅實(shí)現(xiàn)網(wǎng)絡(luò)請(qǐng)求嵌套回調(diào)
Carson帶你學(xué)Android:網(wǎng)絡(luò)請(qǐng)求輪詢(有條件)
Carson帶你學(xué)Android:網(wǎng)絡(luò)請(qǐng)求輪詢(無條件)
Carson帶你學(xué)Android:網(wǎng)絡(luò)請(qǐng)求出錯(cuò)重連(結(jié)合Retrofit)
Carson帶你學(xué)Android:合并數(shù)據(jù)源
Carson帶你學(xué)Android:聯(lián)想搜索優(yōu)化
Carson帶你學(xué)Android:功能防抖
Carson帶你學(xué)Android:從磁盤/內(nèi)存緩存中獲取緩存數(shù)據(jù)
Carson帶你學(xué)Android:聯(lián)合判斷


歡迎關(guān)注Carson_Ho的簡書

不定期分享關(guān)于安卓開發(fā)的干貨,追求短、平、快,但卻不缺深度。


請(qǐng)點(diǎn)贊!因?yàn)槟愕墓膭?lì)是我寫作的最大動(dòng)力!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容