Android RxJava應用:網絡請求輪詢(有條件)

前言

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

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

  • RxJava如此受歡迎的原因,在于其提供了豐富 & 功能強大的操作符,幾乎能完成所有的功能需求
  • 今天,我將為大家?guī)?Rxjava創(chuàng)建操作符的實際開發(fā)需求場景:有條件的輪詢需求 ,并結合RetrofitRxJava 實現(xiàn),希望大家會喜歡。

Carson帶你學RxJava系列文章,包括 原理、操作符、應用場景、背壓等等,請關注看文章:Android:這是一份全面 & 詳細的RxJava學習指南


目錄

示意圖

1. 需求場景

示意圖

注:關于 Rxjava中的repeatWhen() 操作符的使用請看文章Android RxJava:功能性操作符 全面講解


2. 功能說明

采用Get方法對 金山詞霸API 按規(guī)定時間重復發(fā)送網絡請求,從而模擬 輪詢 需求實現(xiàn)

  1. 停止輪詢的條件 = 當輪詢到第4次時
  2. 采用 Gson 進行數(shù)據解析
金山詞典

3. 具體實現(xiàn)

下面,我將結合 RetrofitRxJava 實現(xiàn) 有條件的輪詢需求

3.1 步驟說明

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

本實例側重于說明 RxJava 的輪詢需求,關于Retrofit的使用請看文章:這是一份很詳細的 Retrofit 2.0 使用教程(含實例講解)

3.2 步驟實現(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. 添加 網絡權限
AndroidManifest.xml

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

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

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

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

    //定義 輸出返回數(shù)據 的方法
    public void show() {
        Log.d("RxJava", content.out );
    }
}
步驟3:創(chuàng)建 用于描述網絡請求 的接口

采用 注解 + Observable<...>接口描述 網絡請求參數(shù)

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()是接受網絡請求數(shù)據的方法
}
接下來的步驟均在RxJavafixRxjava.java內實現(xiàn)(請看注釋)

RxJavafixRxjava.java

public class RxJavafixRetrofit extends AppCompatActivity {

    private static final String TAG = "Rxjava";

    // 設置變量 = 模擬輪詢服務器次數(shù)
    private int i = 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ā)送網絡請求 & 通過repeatWhen()進行輪詢
                        observable.repeatWhen(new Function<Observable<Object>, ObservableSource<?>>() {
                            @Override
                            // 在Function函數(shù)中,必須對輸入的 Observable<Object>進行處理,此處使用flatMap操作符接收上游的數(shù)據
                            public ObservableSource<?> apply(@NonNull Observable<Object> objectObservable) throws Exception {
                                // 將原始 Observable 停止發(fā)送事件的標識(Complete() /  Error())轉換成1個 Object 類型數(shù)據傳遞給1個新被觀察者(Observable)
                                // 以此決定是否重新訂閱 & 發(fā)送原來的 Observable,即輪詢
                                // 此處有2種情況:
                                // 1. 若返回1個Complete() /  Error()事件,則不重新訂閱 & 發(fā)送原來的 Observable,即輪詢結束
                                // 2. 若返回其余事件,則重新訂閱 & 發(fā)送原來的 Observable,即繼續(xù)輪詢
                                return objectObservable.flatMap(new Function<Object, ObservableSource<?>>() {
                                    @Override
                                    public ObservableSource<?> apply(@NonNull Object throwable) throws Exception {

                                        // 加入判斷條件:當輪詢次數(shù) = 5次后,就停止輪詢
                                        if (i > 3) {
                                            // 此處選擇發(fā)送onError事件以結束輪詢,因為可觸發(fā)下游觀察者的onError()方法回調
                                            return Observable.error(new Throwable("輪詢結束"));
                                        }
                                        // 若輪詢次數(shù)<4次,則發(fā)送1Next事件以繼續(xù)輪詢
                                        // 注:此處加入了delay操作符,作用 = 延遲一段時間發(fā)送(此處設置 = 2s),以實現(xiàn)輪詢間間隔設置
                                        return Observable.just(1).delay(2000, TimeUnit.MILLISECONDS);
                                    }
                                });

                            }
                        }).subscribeOn(Schedulers.io())               // 切換到IO線程進行網絡請求
                                .observeOn(AndroidSchedulers.mainThread())  // 切換回到主線程 處理請求結果
                                .subscribe(new Observer<Translation>() {
                                    @Override
                                    public void onSubscribe(Disposable d) {
                                    }

                                    @Override
                                    public void onNext(Translation result) {
                                        // e.接收服務器返回的數(shù)據
                                        result.show() ;
                                        i++;
                                    }

                                    @Override
                                    public void onError(Throwable e) {
                                        // 獲取輪詢結束信息
                                        Log.d(TAG,  e.toString());
                                    }

                                    @Override
                                    public void onComplete() {

                                    }
                                });

                    }
    }

3.3 測試結果

示意圖

4. Demo地址

Carson_Ho的Github地址 = RxJava2實戰(zhàn)系列:有條件的輪詢

關于無條件的網絡請求輪詢,具體請看文章Android RxJava 實際應用講解:網絡請求輪詢


5. 總結

  • 本文主要講解了 Rxjava創(chuàng)建操作符的實際開發(fā)需求場景:有條件輪詢需求 ,并結合RetrofitRxJava 實現(xiàn)
  • 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聯(lián)合使用匯總(含實例教程)
Carson帶你學Android:優(yōu)雅實現(xiàn)網絡請求嵌套回調
Carson帶你學Android:網絡請求輪詢(有條件)
Carson帶你學Android:網絡請求輪詢(無條件)
Carson帶你學Android:網絡請求出錯重連(結合Retrofit)
Carson帶你學Android:合并數(shù)據源
Carson帶你學Android:聯(lián)想搜索優(yōu)化
Carson帶你學Android:功能防抖
Carson帶你學Android:從磁盤/內存緩存中獲取緩存數(shù)據
Carson帶你學Android:聯(lián)合判斷


歡迎關注Carson_Ho的簡書

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


請點贊!因為你的鼓勵是我寫作的最大動力!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容