Android RxJava 實際應用講解:網絡請求嵌套回調

前言

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

Github截圖

如果還不瞭解RxJava,請看文章:Android:這是一篇 清晰 & 易懂的Rxjava 入門教程

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

示意圖


目錄

示意圖


1. 需求場景

1.1 背景

需要進行嵌套網絡請求:即在第1個網絡請求成功後,繼續再進行一次網絡請求

如 先進行 用戶註冊 的網絡請求, 待註冊成功後回再繼續發送 用戶登錄 的網絡請求

1.2 衝突

嵌套實現網絡請求較爲複雜,即嵌套調用函數

下面展示的是結合 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();
                    }
                });
    }

1.3 解決方案

結合 RxJava2中的變換操作符FlatMap()實現嵌套網絡請求

關於該操作符的使用具體請看文章:Android RxJava:圖文詳解 變換操作符


2. 功能說明

  • 實現功能:發送嵌套網絡請求(將英文翻譯成中文,翻譯兩次)
  1. 爲了讓大家都能完成Demo,所以通過 公共的金山詞霸API 來模擬 “註冊 - 登錄”嵌套網絡請求
  2. 即先翻譯 Register(註冊),再翻譯 Login(登錄)
  • 實現方案:採用Get方法對 金山詞霸API 發送網絡請求

採用 Gson 進行數據解析

金山詞典


3. 具體實現

下面我將結合 RetrofitRxJava 實現網絡請求嵌套

3.1 步驟說明

  1. 添加依賴
  2. 創建 接收服務器返回數據 的類
  3. 創建 用於描述網絡請求 的接口(區別於Retrofit傳統形式)
  4. 創建 Retrofit 實例
  5. 創建 網絡請求接口實例 並 配置網絡請求參數(區別於Retrofit傳統形式)
  6. 發送網絡請求(區別於Retrofit傳統形式)
  7. 發送網絡請求
  8. 對返回的數據進行處理

本實例側重於說明 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 變換操作符的實際開發需求場景:嵌套回調需求 ,並結合RetrofitRxJava 實現
  • 接下來的時間,我將持續推出 AndroidRxjava 2.0 的一系列文章,包括原理、操作符、應用場景、背壓等等

示意圖



作者:Carson_Ho
鏈接:https://www.jianshu.com/p/5f5d61f04f96
來源:簡書
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章