前言
Rxjava
,由于其基于事件流的鏈式調用、邏輯簡潔 & 使用簡單的特點,深受各大 Android
開發(fā)者的歡迎。
如果還不了解RxJava,請看文章:Android:這是一篇 清晰 & 易懂的Rxjava 入門教程
-
RxJava
如此受歡迎的原因,在于其提供了豐富 & 功能強大的操作符,幾乎能完成所有的功能需求 - 今天,我將為大家?guī)?
Rxjava
創(chuàng)建操作符的實際開發(fā)需求場景:有條件的輪詢需求 ,并結合Retrofit
與RxJava
實現(xiàn),希望大家會喜歡。
Carson帶你學RxJava系列文章,包括 原理、操作符、應用場景、背壓等等,請關注看文章:Android:這是一份全面 & 詳細的RxJava學習指南
目錄
1. 需求場景
注:關于
Rxjava
中的repeatWhen()
操作符的使用請看文章Android RxJava:功能性操作符 全面講解
2. 功能說明
采用Get
方法對 金山詞霸API 按規(guī)定時間重復發(fā)送網絡請求,從而模擬 輪詢 需求實現(xiàn)
- 停止輪詢的條件 = 當輪詢到第4次時
- 采用
Gson
進行數(shù)據解析
3. 具體實現(xiàn)
下面,我將結合 Retrofit
與RxJava
實現(xiàn) 有條件的輪詢需求
3.1 步驟說明
- 添加依賴
- 創(chuàng)建 接收服務器返回數(shù)據 的類
- 創(chuàng)建 用于描述網絡請求 的接口(區(qū)別于
Retrofit
傳統(tǒng)形式) - 創(chuàng)建 Retrofit 實例
- 創(chuàng)建 網絡請求接口實例 并 配置網絡請求參數(shù)(區(qū)別于
Retrofit
傳統(tǒng)形式) - 發(fā)送網絡請求(區(qū)別于
Retrofit
傳統(tǒng)形式) - 發(fā)送網絡請求
- 對返回的數(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 的數(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ā)需求場景:有條件輪詢需求 ,并結合Retrofit
與RxJava
實現(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ā)的干貨,追求短、平、快,但卻不缺深度。