Android RxJava+Retrofit 网络异常捕获、状态码统一处理

前言

近来使用RxJava+Retrofit进行开发,在项目中遇到这样一个需求,联网请求获得数据异常时,需要将对应的Message和StatusCode进行获得并展示,比如:

1.服务器连接Error: 对应的返回404,500等等;

2.没有网络状态(没有4g,3g,是否处于wifi环境下等);

一、简单的获取处理

最简单的处理方式,直接对返回的throwable进行类型判断处理:

//先判断网络环境

if(!NetUtils.is4G(context)){

return;

}

//再联网请求,对throwable进行判断

ServiceHelper.getInstance()

.getModelResult(param1, param2)

.subscribeOn(Schedulers.io())

.observeOn(AndroidSchedulers.mainThread())

.subscribe(new Subscriber() {

@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 extends Subscriber {

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();

// 一定好主动调用下面这一句

onCompleted();

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(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的源码地址:点我点我

android如何获取网络的状态码,Android RxJava+Retrofit网络异常、状态码统一处理相关推荐

  1. Android Studio 获取经纬度

    需求详情 Service中每隔10秒执行一次定位操作(GPS+基站) 定位的结果实时显示在E都市 上(要求得到经度.纬度) Android Studio注册service服务 切记android中的服 ...

  2. Android开发模式之RxJava+Retrofit+MVP(kotlin)

    一共分为两部分,第一部分是RxJava+Retrofit网络请求的使用,一部分是MVP模式结合网络请求 一,RxJava+Retrofit的使用 ①module引入 里面已经封装了OkHttp和Gso ...

  3. Android系统信息获取 之六:网络连接状态信息获取

    Android系统可以通过WIFI和移动网络来连接互联网,系统网络连接状态是通过ConnectivityManager 类来获取的.关键代码如下: [java] view plaincopy Conn ...

  4. Android安卓获取网络状态

    首先在AndroidManifest.xml添加权限 <uses-permission android:name="android.permission.ACCESS_NETWORK_ ...

  5. Android系统信息获取 之十:移动网络相关信息获取

    Android平台移动网络信息主要是通过TelephonyManager类来获取的,通过前面对TelephonyManager的观察Android系统信息获取 之九:TelephonyManager类 ...

  6. android开发获取imei码,Android中获取IMEI码的方法

    我们在开发项目的时候,通常要获取手机的IMEI码,这是开发的必备需求,接下来,爱站技术频道小编就告诉大家Android中获取IMEI码的方法,希望本文的介绍能提高大家的水平. 核心代码:Imei = ...

  7. Android毕业设计——基于Android+Tomcat的网络视频探索系统设计与实现(毕业论文+程序源码)——网络视频探索系统

    基于Android+Tomcat的网络视频探索系统设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于Android+Tomcat的网络视频探索系统设计与实现,文章末尾附有本毕业设计的论文和源 ...

  8. java编程手机gps定位_GPS 获取Gps定位信息的Android源码实例,通过这个JAVA 目,你可能学会GPS在 手机 238万源代码下载- www.pudn.com...

    文件名称: GPS下载 收藏√  [ 5  4  3  2  1 ] 开发工具: Java 文件大小: 59 KB 上传时间: 2013-04-08 下载次数: 22 详细说明:获取Gps定位信息的A ...

  9. 获取并编译linux源码,android获取源代码、编译、命令

    ---my--- 正确的编译android sdk: cd myandroid . ./build/envsetup.sh lunch sdk-eng make sdk //或者: make PROD ...

最新文章

  1. solidworks画白色金属光泽_美人的共通点就是卧蚕,卧蚕真的太重要了,没有也要画出来...
  2. Linux 文件系统常用命令:cat命令
  3. 全年营业额怎么计算_会计税法计算公式大全
  4. python经典好书-python经典书籍推荐
  5. 让数据中心变得更加友好
  6. Linux多线程工作笔记0005---Linux多线程基础_创建线程pthread_create_线程等待_线程终止
  7. 算数运算符与关系运算符_Swift进阶三——运算符相关
  8. python调用其他类中的方法_无法调用其他类中的方法
  9. 苏宁:我们开发百度小程序遇到的那些“坑”
  10. opencv如何获取图像的平均颜色
  11. pfn_to_page 函数
  12. 《云计算核心技术剖析》mini书
  13. VMware Workstation下载和安装
  14. h5耳机线弯曲了怎么办_最烦人的耳机线,总是像麻花一样缠绕在一起,这是什么个道理...
  15. vue倒计时:天时分秒
  16. 6374. 【NOIP2019模拟2019.10.04】结界[生与死的境界]
  17. Nexus搭建Maven私服并使用私服
  18. 【英译中】如何拍好沙滩照2——2014年7月24日
  19. filepath直接指定到文件名吗_快速实现对文件按时间的重命名
  20. Codeforces Round #775 (Div. 2) E. Tyler and Strings

热门文章

  1. 微信小程序 data 赋值
  2. php网页制作过程,网页制作步骤
  3. html页面颜色对应代码
  4. 蓝色蝴蝶(好听的毕业歌)
  5. 金融产品的不可能三角:收益性、风险性、流动性
  6. 你所厌恶的正是别人渴望的
  7. python 抓取网页数据
  8. 九龙证券|重大利好,这板块全线大涨!
  9. 【新知实验室】腾讯云TRTC验证测试
  10. 大学计算机基础方案一,《大学计算机基础》实验实施方案-学生用(7页)-原创力文档...