如何使用 retroift2 实现自定义错误处理
How to implement custom error handling with retroift2
我用基本改造 Call
对象调用 api:
public interface dataApi {
@GET("animal/cats")
Call<AllAnimals> getAllData(
@Query("api_key") String apiKey
);
}
我可以像这样在我的视图模型中得到响应:
call.enqueue(new Callback<AllAnimals>() {
@Override
public void onResponse(Call<AllAnimals> call, Response<AllAnimals> response) {
animals.setValue(response.body());
}
@Override
public void onFailure(Call<AllAnimals> call, Throwable t) {
Log.i(TAG, "onFailure: " + t);
}
});
没什么特别的。
我对这种方法有几个问题
FIRST - 例如,如果我给出了错误的 api 键,响应应该给我一个问题代码的响应,而不是我只是得到 null正文。
SECOND 我计划有更多的 api 调用,这是一个巨大的代码重复来处理我编写的每个调用的错误。
如何针对这种情况实施自定义错误处理,这也适用于其他调用?
我认为您可以使用 okhttp interceptor 并定义自己的 ResponseBody 转换器来解决您的问题。
- 首先拦截你感兴趣的请求和响应;
- 其次,检查响应,如果响应失败则修改响应体为空。
定义一个简单的拦截器
Interceptor interceptor = new Interceptor() {
@Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
String url = request.url().toString();
System.out.println(request.url());
okhttp3.Response response = chain.proceed(request);
if (!response.isSuccessful() && url.contains("animal/cats")) {
// request failed begin to modify response body
response = response.newBuilder()
.body(ResponseBody.create(MediaType.parse("application/json"), new byte[] {}))
.build();
}
return response;
}
};
定义自己的 ResponseBody 转换器
来自 com.squareup.retrofit2:converter-jackson 的大部分代码我们只添加两行:
final class JacksonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private final ObjectReader adapter;
JacksonResponseBodyConverter(ObjectReader adapter) {
this.adapter = adapter;
}
@Override public T convert(ResponseBody value) throws IOException {
try {
if (value.contentLength() == 0) {
return null;
}
return adapter.readValue(value.charStream());
} finally {
value.close();
}
}
}
添加以下代码:
if (value.contentLength() == 0) {
return null;
}
我用基本改造 Call
对象调用 api:
public interface dataApi {
@GET("animal/cats")
Call<AllAnimals> getAllData(
@Query("api_key") String apiKey
);
}
我可以像这样在我的视图模型中得到响应:
call.enqueue(new Callback<AllAnimals>() {
@Override
public void onResponse(Call<AllAnimals> call, Response<AllAnimals> response) {
animals.setValue(response.body());
}
@Override
public void onFailure(Call<AllAnimals> call, Throwable t) {
Log.i(TAG, "onFailure: " + t);
}
});
没什么特别的。
我对这种方法有几个问题
FIRST - 例如,如果我给出了错误的 api 键,响应应该给我一个问题代码的响应,而不是我只是得到 null正文。
SECOND 我计划有更多的 api 调用,这是一个巨大的代码重复来处理我编写的每个调用的错误。
如何针对这种情况实施自定义错误处理,这也适用于其他调用?
我认为您可以使用 okhttp interceptor 并定义自己的 ResponseBody 转换器来解决您的问题。
- 首先拦截你感兴趣的请求和响应;
- 其次,检查响应,如果响应失败则修改响应体为空。
定义一个简单的拦截器
Interceptor interceptor = new Interceptor() {
@Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
String url = request.url().toString();
System.out.println(request.url());
okhttp3.Response response = chain.proceed(request);
if (!response.isSuccessful() && url.contains("animal/cats")) {
// request failed begin to modify response body
response = response.newBuilder()
.body(ResponseBody.create(MediaType.parse("application/json"), new byte[] {}))
.build();
}
return response;
}
};
定义自己的 ResponseBody 转换器
来自 com.squareup.retrofit2:converter-jackson 的大部分代码我们只添加两行:
final class JacksonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private final ObjectReader adapter;
JacksonResponseBodyConverter(ObjectReader adapter) {
this.adapter = adapter;
}
@Override public T convert(ResponseBody value) throws IOException {
try {
if (value.contentLength() == 0) {
return null;
}
return adapter.readValue(value.charStream());
} finally {
value.close();
}
}
}
添加以下代码:
if (value.contentLength() == 0) {
return null;
}