android retrofit+rxjava如何处理响应码为非
一、前言
我想绝大多数小伙伴现在都在用Okhttp或者retrofit来做网络请求了吧,毕竟squar出品必属精品。不废话,今天就是来聊聊http请求响应码的问题。大家都知道,android网络请求是通过httpurlconnection来实现的(httpclient已经在最新的Google源码中废弃),在发起网络请求以后,会有一个Response对象来给我们返回响应信息,而且只有在response code为200的时候才是响应成功,400是请求的url中包含非法字符次,404是请求的url不存在,500是服务器内部出错。
下面给个大致的归类
状态码 | 响应类别 | 说明 |
---|---|---|
1XX | 信息性状态码 | 服务器正在处理请求 |
2XX | 成功状态码 | 请求已正常处理完毕 |
3XX | 重定向状态码 | 需要进行额外操作以完成请求 |
4XX | 客户端错误状态码 | 客户端原因导致服务器无法处理请求 |
5XX | 服务器错误状态码 | 服务器原因导致响应请求出错 |
二、一般的retrofit+rxjava的请求方式如下
mModel.getOneDayTempData(timestamp)
.subscribe(new Observer<TemperatureBean>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(TemperatureBean temperatureBean) {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
如果响应成功,也就是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);
}
});
果然在这个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;
}
}
果然这里有我想要的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();
}
}
我公司的后台有部分errorCode和errorMsg是放在为500的这个异常信息里面的,我必须要去处理这个onError(Throwable e),拿到这里面的信息去提示用户,这样才能保证程序的健壮性。好了,希望能帮到有同样需要的小伙伴吧!