Android RxJava操作符的学习---功能性操作符--网络请求出错重连(结合Retrofit)
1. 需求场景
2. 功能说明
- 功能需求说明
- 功能逻辑
实例说明
在本例子中:采用Get
方法对 金山词霸API 发送网络请求
- 通过 断开网络连接 模拟 网络异常错误(恢复网络即可成功发送请求)
- 限制重试次数 = 10次
- 采用
Gson
进行数据解析
3. 具体实现
下面,我将结合 Retrofit
与RxJava
实现 网络请求出错重连 功能
3.1 步骤说明
- 添加依赖
- 创建 接收服务器返回数据 的类
- 创建 用于描述网络请求 的接口(区别于
Retrofit
传统形式) - 创建
Retrofit
实例 - 创建 网络请求接口实例 并 配置网络请求参数(区别于
Retrofit
传统形式) - 发送网络请求(区别于
Retrofit
传统形式) - 发送网络请求
- 对返回的数据进行处理
下面,将进行详细的功能说明。
本实例侧重于说明
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 的数据格式,创建 接收服务器返回数据 的类:
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() {Log.d("RxJava", content.out );}
}
步骤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()是接受网络请求数据的方法
}
接下来的步骤均在RxJavafixRxjava.java内实现(请看注释)
RxJavafixRxjava.java
public class RxJavafixRetrofit2 extends AppCompatActivity {private static final String TAG = "RxJava";// 设置变量// 可重试次数private int maxConnectCount = 10;// 当前已重试次数private int currentRetryCount = 0;// 重试等待时间private int waitRetryTime = 0;@Overrideprotected 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<...>形式 对 网络请求 进行封装Observable<Translation> observable = request.getCall();// 步骤4:发送网络请求 & 通过retryWhen()进行重试// 注:主要异常才会回调retryWhen()进行重试observable.retryWhen(new Function<Observable<Throwable>, ObservableSource<?>>() {@Overridepublic ObservableSource<?> apply(@NonNull Observable<Throwable> throwableObservable) throws Exception {// 参数Observable<Throwable>中的泛型 = 上游操作符抛出的异常,可通过该条件来判断异常的类型return throwableObservable.flatMap(new Function<Throwable, ObservableSource<?>>() {@Overridepublic ObservableSource<?> apply(@NonNull Throwable throwable) throws Exception {// 输出异常信息Log.d(TAG, "发生异常 = "+ throwable.toString());/*** 需求1:根据异常类型选择是否重试* 即,当发生的异常 = 网络异常 = IO异常 才选择重试*/if (throwable instanceof IOException){Log.d(TAG, "属于IO异常,需重试" );/*** 需求2:限制重试次数* 即,当已重试次数 < 设置的重试次数,才选择重试*/if (currentRetryCount < maxConnectCount){// 记录重试次数currentRetryCount++;Log.d(TAG, "重试次数 = " + currentRetryCount);/*** 需求2:实现重试* 通过返回的Observable发送的事件 = Next事件,从而使得retryWhen()重订阅,最终实现重试功能** 需求3:延迟1段时间再重试* 采用delay操作符 = 延迟一段时间发送,以实现重试间隔设置** 需求4:遇到的异常越多,时间越长* 在delay操作符的等待时间内设置 = 每重试1次,增多延迟重试时间1s*/// 设置等待时间waitRetryTime = 1000 + currentRetryCount* 1000;Log.d(TAG, "等待时间 =" + waitRetryTime);return Observable.just(1).delay(waitRetryTime, TimeUnit.MILLISECONDS);}else{// 若重试次数已 > 设置重试次数,则不重试// 通过发送error来停止重试(可在观察者的onError()中获取信息)return Observable.error(new Throwable("重试次数已超过设置次数 = " +currentRetryCount + ",即 不再重试"));}}// 若发生的异常不属于I/O异常,则不重试// 通过返回的Observable发送的事件 = Error事件 实现(可在观察者的onError()中获取信息)else{return Observable.error(new Throwable("发生了非网络异常(非I/O异常)"));}}});}}).subscribeOn(Schedulers.io()) // 切换到IO线程进行网络请求.observeOn(AndroidSchedulers.mainThread()) // 切换回到主线程 处理请求结果.subscribe(new Observer<Translation>() {@Overridepublic void onSubscribe(Disposable d) {}@Overridepublic void onNext(Translation result) {// 接收服务器返回的数据Log.d(TAG, "发送成功");result.show();}@Overridepublic void onError(Throwable e) {// 获取停止重试的信息Log.d(TAG, e.toString());}@Overridepublic void onComplete() {}});}
}
3.3 测试结果
- 一开始先通过 断开网络连接 模拟 网络异常错误,即开始重试;
- 等到第4次重试后恢复网络连接,即无发生网络异常错误,此时重试成功
Android RxJava操作符的学习---功能性操作符--网络请求出错重连(结合Retrofit)相关推荐
- Android RxJava操作符的学习---功能性操作符--(有条件)网络请求轮询(结合Retrofit)
1. 需求场景 2. 功能说明 采用Get方法对 金山词霸API 按规定时间重复发送网络请求,从而模拟 轮询 需求实现 停止轮询的条件 = 当轮询到第4次时 采用 Gson 进行数据解析 3. 具体实 ...
- Android RxJava操作符的学习---功能性操作符
3.4 功能性操作符 作用 辅助被观察者(Observable) 在发送事件时实现一些功能性需求 实际应用场景 连接(订阅) 观察者 & 被观察者 线程调度(切换) 错误处理 事件生命周期操作 ...
- Android RxJava操作符的学习---变换操作符---网络请求嵌套回调
变换操作符的主要开发需求场景 = 嵌套回调(Callback hell) 下面,我将采用一个实际应用场景实例来讲解嵌套回调(Callback hell) 1. 需求场景 1.1 背景 需要进行嵌套网络 ...
- Android RxJava操作符的学习---创建操作符--(无条件)网络请求轮询
1. 需求场景 2. 功能说明 本文将采用Get方法对 金山词霸API 按规定时间 重复发送网络请求,从而模拟 轮询 需求实现 采用 Gson 进行数据解析 3. 具体实现 下面结合 Retrofit ...
- android 网络时区 错误,React native 安卓机器上调试代码报错:网络请求出错TypeError: Network request failed...
React native 安卓机器上调试代码报错:网络请求出错TypeError: Network request failed 安卓机器 usb连接调试 报错信息 TypeError: Networ ...
- Android 9.0/P(android p指安卓9.0版本) okhttp3网络请求出错
已经在AndroidManifest.xml申请网络权限,在8.0以下的系统中网络访问正常,但是9.0中出现网络请求失败 Android 9.0的网络请求失败如下图: 出现这个错误的原因是:从Andr ...
- Android RxJava操作符的学习---过滤操作符----功能防抖
1. 需求场景 2. 功能说明 3. 具体实现 // 注册控件Button button;button = (Button)findViewById(R.id.button);/** 1. 此处采用了 ...
- Android RxJava操作符的学习---过滤操作符
3.5 过滤操作符 作用 过滤 / 筛选 被观察者(Observable)发送的事件 & 观察者 (Observer)接收的事件 应用场景 根据 指定条件 过滤事件 根据 指定事件数量 过滤事 ...
- Android RxJava操作符的学习---创建操作符
RxJava如此受欢迎的原因,在于其提供了丰富 & 功能强大的操作符,几乎能完成所有的功能需求 1. 简介 RxJava 操作符的具体简介如下: 2. 类型 RxJava功能强大,所以其对应的 ...
最新文章
- Python3中迭代器介绍
- 对RPM软件包的查询操作
- 28和lba48命令格式区别_linux硬盘分区、格式化、挂载超详细步骤
- Hadoop之HDFS应用
- docker依赖的Linux内核特性及各命令参数说明
- git回退到历史版本并提交到远程分支
- 赋值语句、变量、数学表达式、位运算详解(C++)
- 关于动网论坛、动力起航、自由动力、动易、动感购物、乔客、织梦CMS.
- 科来网络回溯分析系统-回溯追踪ARP扫描攻击
- Oracle卸载(无universal installer)
- 在mac上使用nginx配置codeigniter框架一直显示404的问题的一种方法(重启)
- Go语言优秀的Revel开源框架推荐
- 信号偏移成为边界地区呼吸的痛
- 一个Android开发者开博一周年的成长日记——送给不知如何下手的【初级开发者】和【在校生】
- 微博粉丝精灵_天猫精灵“布蕉绿”新品上线,解锁智能音箱潮流新玩法!
- QImage 图像格式小结 Format_RGB32
- 展望 | 2023年十大科技趋势
- 亲缘进程、非亲缘进程-共享内存与信号
- Epic 起诉苹果,G 胖无辜背锅,要求其公开数百款第三方游戏 6 年的数据,网友:G 胖实冤!...
- WireShark的下载与安装