android retrofit+rxjava如何处理响应码为非200的情况?

android retrofit+rxjava如何处理响应码为非200的情况?

一、前言

我想绝大多数小伙伴现在都在用Okhttp或者retrofit来做网络请求了吧,毕竟squar出品必属精品。不废话,今天就是来聊聊http请求响应码的问题。大家都知道,android网络请求是通过httpurlconnection来实现的(httpclient已经在最新的Google源码中废弃),在发起网络请求以后,会有一个Response对象来给我们返回响应信息,而且只有在response code为200的时候才是响应成功,400是请求的url中包含非法字符次,404是请求的url不存在,500是服务器内部出错。

下面给个大致的归类

状态码 响应类别 说明
1XX 信息性状态码 服务器正在处理请求
2XX 成功状态码 请求已正常处理完毕
3XX 重定向状态码 需要进行额外操作以完成请求
4XX 客户端错误状态码 客户端原因导致服务器无法处理请求
5XX 服务器错误状态码 服务器原因导致响应请求出错

android http code响应码 状态码

二、一般的retrofit+rxjava的请求方式如下

mModel.getOneDayTempData(timestamp)
                .subscribe(new Observer() {
                    @Override
                    public void onSubscribe(Disposable d) {   
                    }
                    @Override
                    public void onNext(TemperatureBean temperatureBean) {
                    }
                    @Override
                    public void onError(Throwable e) {
                    }
                    @Override
                    public void onComplete() {
                    }
                });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

如果响应成功,也就是response code为200的时候,会执行onNext,如果响应码非200的情况下会执行onError(),而且在onNext()的时候可以获取到响应信息,这是大家都知道的。但是响应失败的时候,onError(Throwable e) 这个方法的参数是Throwable对象,我们通过e.toString()来打印一下结果

我故意发送了一个错误的请求,结果只是打印了头部信息,并没有我们想要的response

retrofit2.adapter.rxjava2.HttpException: HTTP 500 Internal Server Error

在这里我就困扰了好久,按照httpurlconnection,就算是500也能拿到这个response的,我想会不会是这个Throwable信息不全,然后我想既然retrofit是通过okhttp来实现请求的,我就用okhttp试试

OkHttpUtils.doPostRequest(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
            }
            @Override
            public void onResponse(Call call, Response response) {
                String body = response.body().string();
                Log.i(TAG, "onResponse: "+body);
            }
        });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

果然在这个response里面拿到了code为500的时候的body信息

所以现在只要我能把onError(Throwable e)这个Throwable转换成Response不就行了吗?这时候查看了一下源码,Exception是继承于Throwable的,所以来看看这个HttpException的源码
HttpException部分源码

public class HttpException extends Exception {
  private static String getMessage(Response response) {
    if (response == null) throw new NullPointerException("response == null");
    return "HTTP " + response.code() + " " + response.message();
  }
  private final int code;
  private final String message;
  private final transient Response response;
  public HttpException(Response response) {
    super(getMessage(response));
    this.code = response.code();
    this.message = response.message();
    this.response = response;
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

果然这里有我想要的code和Response对象,这下就好办了,我只需要把Throwable向下转型转成HttpException就可以获取信息了

向下转型的方式如下

 if (throwable instanceof HttpException){
          ResponseBody body = ((HttpException) throwable).response().errorBody();
          try {
                 Log.i(TAG, "onFailure: "+body.string());
             } catch (IOException e) {
                  e.printStackTrace();
             }
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

我公司的后台有部分errorCode和errorMsg是放在为500的这个异常信息里面的,我必须要去处理这个onError(Throwable e),拿到这里面的信息去提示用户,这样才能保证程序的健壮性。好了,希望能帮到有同样需要的小伙伴吧!

你可能感兴趣的:(android,rxjava,okhttp)