返回
Retrofit 深入剖析:自定义 CallAdapter,优雅处理错误信息
Android
2024-01-04 03:44:47
Android Retrofit 源码系列(二)~ 自定义 CallAdapter
在上一篇 Retrofit 源码分析文章中,我们深入探讨了 CallAdapter 在 Retrofit 中的关键作用。今天,我们将更进一步,学习如何自定义 CallAdapter,从而优雅地处理错误信息。通过剖析源码,我们将揭开自定义 CallAdapter 背后的秘密。
自定义 CallAdapter 的必要性
默认情况下,Retrofit 会将网络请求的结果以 Call 对象的形式返回。Call 对象提供了丰富的 API,用于管理网络请求的生命周期。然而,当发生错误时,Retrofit 并不会对错误信息进行统一的封装,这给后续的错误处理带来了不便。
自定义 CallAdapter 可以解决这个问题。通过创建一个自定义的 CallAdapter,我们可以对错误信息进行统一的封装和处理,从而简化代码并提高可维护性。
创建自定义 CallAdapter
让我们从一个简单的示例开始,自定义一个 CallAdapter 来封装常见的网络错误,例如超时和连接失败。
public class ErrorHandlingCallAdapterFactory extends CallAdapter.Factory {
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
return new ErrorHandlingCallAdapter<>(retrofit);
}
private static class ErrorHandlingCallAdapter<R> implements CallAdapter<R, Call<R>> {
private final Retrofit retrofit;
public ErrorHandlingCallAdapter(Retrofit retrofit) {
this.retrofit = retrofit;
}
@Override
public Type responseType() {
return getRawType(getParameterUpperBound(0, getCallAdapterMethod().getGenericReturnType()));
}
@Override
public Call<R> adapt(Call<R> call) {
return new ErrorHandlingCall<>(call, retrofit);
}
}
}
工作原理:
ErrorHandlingCallAdapter
类实现了CallAdapter.Factory
接口,用于创建自定义的 CallAdapter。get()
方法检查返回类型是否为Call
。如果不是,则返回null
。ErrorHandlingCallAdapter
的内部类实现了CallAdapter
接口,并负责实际的错误处理逻辑。adapt()
方法将原始的Call
对象包装在一个ErrorHandlingCall
对象中,该对象负责在错误发生时进行封装。
自定义 CallAdapter 的执行流程
让我们一步步分析 ErrorHandlingCall
的执行流程:
private static class ErrorHandlingCall<R> implements Call<R> {
private final Call<R> delegate;
private final Retrofit retrofit;
public ErrorHandlingCall(Call<R> delegate, Retrofit retrofit) {
this.delegate = delegate;
this.retrofit = retrofit;
}
@Override
public Response<R> execute() throws IOException {
try {
return delegate.execute();
} catch (Throwable throwable) {
throw RetrofitException.convertException(throwable);
}
}
@Override
public void enqueue(Callback<R> callback) {
delegate.enqueue(new ErrorHandlingCallback<>(callback, retrofit));
}
@Override
public boolean isExecuted() {
return delegate.isExecuted();
}
@Override
public void cancel() {
delegate.cancel();
}
@Override
public boolean isCanceled() {
return delegate.isCanceled();
}
}
工作原理:
ErrorHandlingCall
的构造函数接收原始的Call
对象和 Retrofit 实例。execute()
方法在发生错误时将其包装为RetrofitException
。enqueue()
方法将回调包装在一个ErrorHandlingCallback
对象中,该对象负责将封装后的错误传递给原始回调。- 其他方法将委托给原始的
Call
对象。
集成到 Retrofit
要集成我们的自定义 CallAdapter,我们只需在 Retrofit.Builder
中使用 addCallAdapterFactory()
方法即可。
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://example.com/")
.addCallAdapterFactory(new ErrorHandlingCallAdapterFactory())
.build();
总结
通过自定义 CallAdapter,我们实现了对 Retrofit 错误信息的统一封装和处理。这不仅提高了代码的可维护性,而且使错误处理更加健壮和优雅。通过分析源码,我们深入了解了自定义 CallAdapter 的执行流程,为我们提供了强大且可定制的工具,用于管理 Retrofit 网络请求。