Android RxJava+Retrofit网络异常、状态码统一处理
来源:互联网 发布:网络交友的危害翻译 编辑:程序博客网 时间:2024/05/21 16:58
Android RxJava+Retrofit 网络异常捕获、状态码统一处理
前言
近来使用RxJava+Retrofit进行开发,在项目中遇到这样一个需求,联网请求获得数据异常时,需要将对应的Message和StatusCode进行获得并展示,比如:
1.服务器连接Error: 对应的返回404,500等等;
2.没有网络状态(没有4g,3g,是否处于wifi环境下等);
参考文章:
Rxjava +Retrofit 你需要掌握的几个技巧,Retrofit缓存,RxJava封装,统一对有无网络处理,异常处理, 返回结果问题 @码小白
一、简单的获取处理
最简单的处理方式,直接对返回的throwable进行类型判断处理:
//先判断网络环境if(!NetUtils.is4G(context)){ return;}//再联网请求,对throwable进行判断ServiceHelper.getInstance() .getModelResult(param1, param2) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Subscriber<Model>() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { if(e instanceof HttpException){ //获取对应statusCode和Message HttpException exception = (HttpException)e; String message = exception.response().message(); int code = exception.response().code(); }else if(e instanceof SSLHandshakeException){ //接下来就是各种异常类型判断... }else if(e instanceof ...){ }... ... } @Override public void onNext(Model model) { } });
显然,代码并不难以理解,但是非常麻烦,总不至于每次都要进行这样的大块代码复制粘贴吧。
请注意,进行类型判断的的HttpException为
import retrofit2.adapter.rxjava.HttpException;
所以需要我们依赖:
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
二、NetErrorUtil封装
1.首先我们创建一个Throwable的管理类
public class ExceptionHandle { private static final int UNAUTHORIZED = 401; private static final int FORBIDDEN = 403; private static final int NOT_FOUND = 404; private static final int REQUEST_TIMEOUT = 408; private static final int INTERNAL_SERVER_ERROR = 500; private static final int BAD_GATEWAY = 502; private static final int SERVICE_UNAVAILABLE = 503; private static final int GATEWAY_TIMEOUT = 504; public static ResponeThrowable handleException(Throwable e) { ResponeThrowable ex; Log.i("tag", "e.toString = " + e.toString()); if (e instanceof HttpException) { HttpException httpException = (HttpException) e; ex = new ResponeThrowable(e, ERROR.HTTP_ERROR); switch (httpException.code()) { case UNAUTHORIZED: case FORBIDDEN: case NOT_FOUND: case REQUEST_TIMEOUT: case GATEWAY_TIMEOUT: case INTERNAL_SERVER_ERROR: case BAD_GATEWAY: case SERVICE_UNAVAILABLE: default: //ex.code = httpException.code(); ex.message = "网络错误"; break; } return ex; } else if (e instanceof ServerException) { ServerException resultException = (ServerException) e; ex = new ResponeThrowable(resultException, resultException.code); ex.message = resultException.message; return ex; } else if (e instanceof JsonParseException || e instanceof JSONException /*|| e instanceof ParseException*/) { ex = new ResponeThrowable(e, ERROR.PARSE_ERROR); ex.message = "解析错误"; return ex; } else if (e instanceof ConnectException) { ex = new ResponeThrowable(e, ERROR.NETWORD_ERROR); ex.message = "连接失败"; return ex; } else if (e instanceof javax.net.ssl.SSLHandshakeException) { ex = new ResponeThrowable(e, ERROR.SSL_ERROR); ex.message = "证书验证失败"; return ex; } else { ex = new ResponeThrowable(e, ERROR.UNKNOWN); ex.message = "未知错误"; return ex; } } /** * 约定异常 */ class ERROR { /** * 未知错误 */ public static final int UNKNOWN = 1000; /** * 解析错误 */ public static final int PARSE_ERROR = 1001; /** * 网络错误 */ public static final int NETWORD_ERROR = 1002; /** * 协议出错 */ public static final int HTTP_ERROR = 1003; /** * 证书出错 */ public static final int SSL_ERROR = 1005; } public static class ResponeThrowable extends Exception { public int code; public String message; public ResponeThrowable(Throwable throwable, int code) { super(throwable); this.code = code; } } /** * ServerException发生后,将自动转换为ResponeThrowable返回 */ class ServerException extends RuntimeException { int code; String message; }}
在这个类中,我们把throwable进行类型统一判断:
1.若为Exception,我们再进行判断,根据不同种类的Exception,转化为ResponeThrowable返回,并赋予不同的code和message;
2.若为RuntimeException,我们再转换为ResponeThrowable返回;
总而言之,我们把获取到的异常,通过handleException()方法,转化为统一的ResponeThrowable返回,这个对象包含code和message。
2.然后是创建一个新的Subscriber基类
/** * Subscriber基类,可以在这里处理client网络连接状况 * (比如没有wifi,没有4g,没有联网等) * Created by fcn-mq on 2017/4/19. */public abstract class MySubscriber<T> extends Subscriber<T> { private Context context; public MySubscriber(Context context) { this.context = context; } @Override public void onStart() { super.onStart(); Log.i("tag","MySubscriber.onStart()"); //接下来可以检查网络连接等操作 if (!NetworkUtil.isNetworkAvailable(context)) { Toast.makeText(context, "当前网络不可用,请检查网络情况", Toast.LENGTH_SHORT).show(); // 一定好主动调用下面这一句,取消本次Subscriber订阅 if (!isUnsubscribed()) { unsubscribe(); } return; } } @Override public void onError(Throwable e) { Log.e("tag","MySubscriber.throwable ="+e.toString()); Log.e("tag","MySubscriber.throwable ="+e.getMessage()); if(e instanceof Exception){ //访问获得对应的Exception onError(ExceptionHandle.handleException(e)); }else { //将Throwable 和 未知错误的status code返回 onError(new ExceptionHandle.ResponeThrowable(e,ExceptionHandle.ERROR.UNKNOWN)); } } public abstract void onError(ExceptionHandle.ResponeThrowable responeThrowable); @Override public void onCompleted() { Log.i("tag","MySubscriber.onComplete()"); }}
这个就好理解了,我们可以在基类中统一进行客户端网络环境的判断,或者当网络异常发生时,统一转换为
ResponeThrowable,在onError(ExceptionHandle.ResponeThrowable responeThrowable)中回调,这个abstract的回调方法需要我们自己实现。
3.代码中使用:
new Retrofit.Builder() .baseUrl(ConstantsApi.BASE_DOUBAN) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .client(client) .build() .create(DoubanMovieService.class)//获得对应的service对象 .getModelResult(param1, param2) //网络请求 .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new MySubscriber<Model>(context) { @Override public void onNext(Model model) { ... } @Override public void onError(ExceptionHandle.ResponeThrowable throwable) { LogUtil.m("tag","throwable =" + throwable.toString()); //接下来就可以根据状态码进行处理... int statusCode = throwable.code; switch (statusCode){ case ExceptionHandle.ERROR.SSL_ERROR: break; case ExceptionHandle.ERROR.UNKNOWN: break; case ExceptionHandle.ERROR.PARSE_ERROR: break; case ExceptionHandle.ERROR.NETWORD_ERROR: break; case ExceptionHandle.ERROR.HTTP_ERROR: break; } } });
最后是NetErrorUtil的源码地址:点我点我
【GitHub地址】https://github.com/ButQingMei/Samples.git
- Android RxJava+Retrofit网络异常、状态码统一处理
- Rxjava +Retrofit 你需要掌握的几个技巧,Retrofit缓存,RxJava封装,统一对有无网络处理,异常处理, 返回结果问题
- RxJava结合Retrofit对网络请求结果的统一处理
- Retrofit+RxJava实战日志(3)-网络异常处理
- OkHttp Retrofit RxJava 统一错误处理
- Retrofit+RxJava处理网络请求
- retrofit&rxjava&gson请求成功后回调的统一处理
- Android异常统一处理
- 使用MVP+Retrofit+RxJava实现的的Android Demo (下)使用Retrofit+RxJava处理网络请求
- Android】RxJava + Retrofit完成网络请求
- Android 网络请求框架之Rxjava+Retrofit
- Android网络请求(二)retrofit+rxjava
- Android 网络请求框架之Rxjava+Retrofit
- 【Android】RxJava + Retrofit完成网络请求
- Android 网络请求框架之Rxjava+Retrofit
- Android 网络请求框架之Rxjava+Retrofit
- android 网络框架学习(okhttp,retrofit,rxjava)
- 【Android】RxJava + Retrofit完成网络请求
- tarjan最小割点算法模板
- React Native之七牛
- JAVA的Random类的用法详解
- imx6 u-boot 启动 Can't find PMIC:PFUZE100
- eclipse ant认识
- Android RxJava+Retrofit网络异常、状态码统一处理
- 数据存储和访问之商品展示案例
- 数字图像处理实验三 图像轮廓提取与边缘检测
- postgresql
- poj 2137 Cowties
- 交易清单(京东2016实习生真题)
- 近几年目标跟踪算法发展综述(下)
- Git 安装与使用详解
- [整理]php常用函数及运用场景----字符串函数str