Android OKHTTP 网络请求出错重连(结合Retrofit RxJava)--retryWhen命令符

本文主要是介绍Android OKHTTP 网络请求出错重连(结合Retrofit RxJava)--retryWhen命令符,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

链接:
https://www.jianshu.com/p/508c30aef0c1
网络抖动可能会产生大量的网络断链,所以httpClient自动重试是非常有必要的

需求1:根据异常类型选择是否重试
* 即,当发生的异常 = 网络异常 = IO异常 才选择重试
需求2:实现重试
* 通过返回的Observable发送的事件 = Next事件,从而使得retryWhen()重订阅,最终实现重试功能

需求3:延迟1段时间再重试
* 采用delay操作符 = 延迟一段时间发送,以实现重试间隔设置

需求4:遇到的异常越多,时间越长
* 在delay操作符的等待时间内设置 = 每重试1次,增多延迟重试时间0.5s
在这里插入图片描述

Retrofit.Builder builder = new Retrofit.Builder();builder.baseUrl(mBuilder.mBaseUrl).client(providerHttpClient()).addConverterFactory(GsonConverterFactory.create(gson)).addCallAdapterFactory(FRxJava2CallAdapterFactory.createWithScheduler());
public class FRxJava2CallAdapterFactory extends CallAdapter.Factory {private RxJava2CallAdapterFactory wrappedCallAdapterFactory;private FRxJava2CallAdapterFactory() {wrappedCallAdapterFactory = RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io());}public static FRxJava2CallAdapterFactory createWithScheduler() {return new FRxJava2CallAdapterFactory();}@Overridepublic CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {CallAdapter<?, ?> callAdapter = wrappedCallAdapterFactory.get(returnType, annotations,retrofit);if (callAdapter == null) {return null;}Class<?> rawType = getRawType(returnType);boolean isCompletable = rawType == Completable.class;boolean isFlowable = rawType == Flowable.class;boolean isSingle = rawType == Single.class;boolean isMaybe = rawType == Maybe.class;return new FCallAdapter(callAdapter, isCompletable, isFlowable, isMaybe, isSingle);}private static class FCallAdapter<R> implements CallAdapter<R, Observable> {//we might handle other rawtype in the future. but currently only for Observable.private final boolean isCompletable;private final boolean isFlowable;private final boolean isMaybe;private final boolean isSingle;private CallAdapter wrapped;FCallAdapter(CallAdapter callAdapter, boolean isCompletable,boolean isFlowable, boolean isMaybe, boolean isSingle) {wrapped = callAdapter;this.isCompletable = isCompletable;this.isFlowable = isFlowable;this.isMaybe = isMaybe;this.isSingle = isSingle;}@Overridepublic Type responseType() {return wrapped.responseType();}@Overridepublic Observable<?> adapt(Call<R> call) {String retryOnFailure = call.request().header("retryOnFailure");boolean retry = retryOnFailure != null && Boolean.valueOf(retryOnFailure);return ((Observable) wrapped.adapt(call))
//                    .onErrorResumeNext()
//                    .timeout(10 * 1000, TimeUnit.MILLISECONDS).subscribeOn(Scheduler.ioThread()).observeOn(Scheduler.mainThread()).doAfterNext(new Consumer() {@Overridepublic void accept(Object o) throws Exception {
//                            if (!IOVCloudRepository.getInstance().getIovCloudRepositoryManager
// ().isNetworkAvailable()) {
//                                FFUtils.checkNetworkAccess(null);
//                            }}}).retryWhen(new RetryWhenNetworkException(2))//重试逻辑;}}}

主要的重试逻辑

public class RetryWhenNetworkException implements Function<Observable<? extends Throwable>, Observable<?>> {// 可重试次数private int maxConnectCount = 2;// 当前已重试次数private int currentRetryCount = 0;// 重试等待时间private int waitRetryTime = 0;public RetryWhenNetworkException(int maxConnectCount) {this.maxConnectCount = maxConnectCount;}@Overridepublic Observable<?> apply(Observable<? extends Throwable> throwableObservable) throws Exception {// 参数Observable<Throwable>中的泛型 = 上游操作符抛出的异常,可通过该条件来判断异常的类型return throwableObservable.flatMap(new Function<Throwable, ObservableSource<?>>() {@Overridepublic ObservableSource<?> apply(Throwable throwable) throws Exception {// 输出异常信息FLog.d("发生异常 = " + throwable.toString());/*** 需求1:根据异常类型选择是否重试* 即,当发生的异常 = 网络异常 = IO异常 才选择重试*/if (throwable instanceof IOException ) {
//                if (throwable instanceof TimeoutException ) {
//                    FLog.d("属于IO异常,需重试");FLog.d("属于网络异常,需重试");/*** 需求2:限制重试次数* 即,当已重试次数 < 设置的重试次数,才选择重试*/if (currentRetryCount < maxConnectCount) {// 记录重试次数currentRetryCount++;FLog.d("重试次数 = " + currentRetryCount);/*** 需求2:实现重试* 通过返回的Observable发送的事件 = Next事件,从而使得retryWhen()重订阅,最终实现重试功能** 需求3:延迟1段时间再重试* 采用delay操作符 = 延迟一段时间发送,以实现重试间隔设置** 需求4:遇到的异常越多,时间越长* 在delay操作符的等待时间内设置 = 每重试1次,增多延迟重试时间0.5s*/// 设置等待时间waitRetryTime = 500 + currentRetryCount * 500;FLog.d("等待时间 =" + waitRetryTime);return Observable.just(1).delay(waitRetryTime, TimeUnit.MILLISECONDS);} else {// 若重试次数已 > 设置重试次数,则不重试// 通过发送error来停止重试(可在观察者的onError()中获取信息)return Observable.error(new Throwable("重试次数已超过设置次数 = " + currentRetryCount + ",即 不再重试;"+throwable));}}// 若发生的异常不属于I/O异常,则不重试// 通过返回的Observable发送的事件 = Error事件 实现(可在观察者的onError()中获取信息)else {FLog.e(new Throwable("发生了非网络异常(非I/O异常)"));return Observable.error(throwable);}}});}
}

这篇关于Android OKHTTP 网络请求出错重连(结合Retrofit RxJava)--retryWhen命令符的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/979235

相关文章

Java的栈与队列实现代码解析

《Java的栈与队列实现代码解析》栈是常见的线性数据结构,栈的特点是以先进后出的形式,后进先出,先进后出,分为栈底和栈顶,栈应用于内存的分配,表达式求值,存储临时的数据和方法的调用等,本文给大家介绍J... 目录栈的概念(Stack)栈的实现代码队列(Queue)模拟实现队列(双链表实现)循环队列(循环数组

Android实现在线预览office文档的示例详解

《Android实现在线预览office文档的示例详解》在移动端展示在线Office文档(如Word、Excel、PPT)是一项常见需求,这篇文章为大家重点介绍了两种方案的实现方法,希望对大家有一定的... 目录一、项目概述二、相关技术知识三、实现思路3.1 方案一:WebView + Office Onl

Java中Switch Case多个条件处理方法举例

《Java中SwitchCase多个条件处理方法举例》Java中switch语句用于根据变量值执行不同代码块,适用于多个条件的处理,:本文主要介绍Java中SwitchCase多个条件处理的相... 目录前言基本语法处理多个条件示例1:合并相同代码的多个case示例2:通过字符串合并多个case进阶用法使用

Java中的Lambda表达式及其应用小结

《Java中的Lambda表达式及其应用小结》Java中的Lambda表达式是一项极具创新性的特性,它使得Java代码更加简洁和高效,尤其是在集合操作和并行处理方面,:本文主要介绍Java中的La... 目录前言1. 什么是Lambda表达式?2. Lambda表达式的基本语法例子1:最简单的Lambda表

Java中Scanner的用法示例小结

《Java中Scanner的用法示例小结》有时候我们在编写代码的时候可能会使用输入和输出,那Java也有自己的输入和输出,今天我们来探究一下,对JavaScanner用法相关知识感兴趣的朋友一起看看吧... 目录前言一 输出二 输入Scanner的使用多组输入三 综合练习:猜数字游戏猜数字前言有时候我们在

Spring Security+JWT如何实现前后端分离权限控制

《SpringSecurity+JWT如何实现前后端分离权限控制》本篇将手把手教你用SpringSecurity+JWT搭建一套完整的登录认证与权限控制体系,具有很好的参考价值,希望对大家... 目录Spring Security+JWT实现前后端分离权限控制实战一、为什么要用 JWT?二、JWT 基本结构

java解析jwt中的payload的用法

《java解析jwt中的payload的用法》:本文主要介绍java解析jwt中的payload的用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java解析jwt中的payload1. 使用 jjwt 库步骤 1:添加依赖步骤 2:解析 JWT2. 使用 N

springboot项目如何开启https服务

《springboot项目如何开启https服务》:本文主要介绍springboot项目如何开启https服务方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录springboot项目开启https服务1. 生成SSL证书密钥库使用keytool生成自签名证书将

Java实现优雅日期处理的方案详解

《Java实现优雅日期处理的方案详解》在我们的日常工作中,需要经常处理各种格式,各种类似的的日期或者时间,下面我们就来看看如何使用java处理这样的日期问题吧,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言一、日期的坑1.1 日期格式化陷阱1.2 时区转换二、优雅方案的进阶之路2.1 线程安全重构2

Android实现两台手机屏幕共享和远程控制功能

《Android实现两台手机屏幕共享和远程控制功能》在远程协助、在线教学、技术支持等多种场景下,实时获得另一部移动设备的屏幕画面,并对其进行操作,具有极高的应用价值,本项目旨在实现两台Android手... 目录一、项目概述二、相关知识2.1 MediaProjection API2.2 Socket 网络