一、Retrofit:Android 网络请求的 “智能翻译官”
Retrofit 是 Android 开发中最流行的网络请求框架之一,它通过动态代理和适配器模式,将复杂的 HTTP 请求封装为简洁的接口调用。核心功能包括:
- 接口抽象:用注解定义 API 接口,自动生成请求逻辑;
- 类型转换:将 HTTP 响应自动转换为 Java/Kotlin 对象;
- 异步处理:无缝集成 RxJava、Coroutines 等异步框架。
二、核心流程:从接口定义到数据获取
以 RxJava2 集成为例,Retrofit 的工作流程可拆解为四步:
三、源码核心模块解析
1. Retrofit 对象创建:配置 “翻译规则”
java
Retrofit retrofit = new Retrofit.Builder()
.client(new OkHttpClient()) // 底层请求引擎
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 响应适配器
.addConverterFactory(GsonConverterFactory.create()) // 数据转换器
.baseUrl("https://api.example.com/") // 基础URL
.build();
- CallAdapterFactory:负责将 OkHttp 的 Call 转换为 RxJava 的 Observable、Flowable 等异步类型;
- ConverterFactory:定义数据转换规则(如 Gson 将 JSON 转为对象);
- OkHttpClient:实际执行 HTTP 请求的底层引擎。
2. 动态代理:接口的 “魔法翻译”
当调用retrofit.create(InfoApi.class)时,Retrofit 通过 Java 动态代理生成接口的代理对象:
java
public <T> T create(final Class<T> service) {
// 生成代理对象,拦截接口方法调用
return Proxy.newProxyInstance(service.getClassLoader(), new Class[]{service},
(proxy, method, args) -> {
// 解析方法注解(@GET、@Query等)
ServiceMethod serviceMethod = loadServiceMethod(method);
// 生成OkHttpCall对象
OkHttpCall okHttpCall = new OkHttpCall(serviceMethod, args);
// 通过CallAdapter转换为目标类型(如Observable)
return serviceMethod.adapt(okHttpCall);
});
}
关键步骤:
- ServiceMethod:解析方法注解,生成请求参数(URL、请求方式、参数);
- OkHttpCall:封装 OkHttp 的 Call,处理请求发送;
- 适配器模式:通过 CallAdapter 将 OkHttp 的 Call 转换为 RxJava 的 Observable。
3. 请求发送:从接口到 HTTP 的 “翻译过程”
以 RxJava2 的 CallAdapter 为例,请求发送流程如下:
-
CallAdapter 转换:
java
// RxJava2CallAdapter将OkHttpCall转换为Observable Observable<Response<T>> observable = isAsync ? new CallEnqueueObservable(call) // 异步请求 : new CallExecuteObservable(call); // 同步请求 -
OkHttp 执行请求:
java
// OkHttpCall的enqueue方法最终调用OkHttp的Call.enqueue call.enqueue(new okhttp3.Callback() { @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) { // 解析响应,转换为Retrofit的Response对象 Response<T> response = parseResponse(rawResponse); callback.onResponse(OkHttpCall.this, response); } }); -
响应转换:
通过 Converter(如 GsonConverter)将 HTTP 响应体转换为目标对象:java
// GsonResponseBodyConverter将JSON转为Java对象 T body = gson.fromJson(responseBody.charStream(), type);
四、核心设计模式:Retrofit 的 “架构密码”
-
动态代理(Dynamic Proxy) :
- 作用:生成接口的代理对象,拦截方法调用并解析注解;
- 场景:
retrofit.create(service)时动态生成接口实现。
-
工厂模式(Factory) :
- CallAdapterFactory、ConverterFactory 负责创建适配器和转换器;
- 示例:
RxJava2CallAdapterFactory.create()生成 RxJava 适配器。
-
责任链模式(Chain of Responsibility) :
- 响应转换链:OkHttp 响应 → Retrofit Response → 目标对象;
- 自定义转换器可插入链中扩展功能。
五、实战优化:让 Retrofit 更强大
1. 自定义 Converter:统一错误处理
java
// 自定义Converter处理统一错误格式
public class ApiResponseConverterFactory extends Converter.Factory {
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type,
Annotation[] annotations,
Retrofit retrofit) {
Type rawType = getRawType(type);
if (rawType == Response.class && type instanceof ParameterizedType) {
Type responseType = getParameterUpperBound(0, (ParameterizedType) type);
return new ApiResponseConverter<>(retrofit.responseBodyConverter(
responseType, annotations, retrofit));
}
return null;
}
private class ApiResponseConverter<T> implements Converter<ResponseBody, Response<T>> {
private final Converter<ResponseBody, T> delegate;
public ApiResponseConverter(Converter<ResponseBody, T> delegate) {
this.delegate = delegate;
}
@Override
public Response<T> convert(ResponseBody body) throws IOException {
// 解析基础响应
ApiResult<T> apiResult = gson.fromJson(body.charStream(), ApiResult.class);
if (apiResult.code != 200) {
// 统一错误处理
throw new ApiException(apiResult.code, apiResult.message);
}
return Response.success(apiResult.data);
}
}
}
2. 取消请求:避免内存泄漏
java
// 通过Tag取消请求
Retrofit retrofit = new Retrofit.Builder()
.client(new OkHttpClient.Builder()
.addInterceptor(chain -> {
Request request = chain.request();
if (request.tag() == "CANCEL_TAG") {
throw new IOException("Request canceled");
}
return chain.proceed(request);
})
.build())
.build();
// 取消请求
retrofit.create(ApiService.class).getUser()
.subscribeOn(Schedulers.io())
.doOnCancel(() -> {
// 清理资源
})
.subscribe();
3. 日志拦截器:调试必备
java
Interceptor loggingInterceptor = chain -> {
Request request = chain.request();
long t1 = System.nanoTime();
Log.d("Retrofit", "请求URL: " + request.url());
Log.d("Retrofit", "请求头: " + request.headers());
Response response = chain.proceed(request);
long t2 = System.nanoTime();
Log.d("Retrofit", "响应码: " + response.code());
Log.d("Retrofit", "响应耗时: " + (t2 - t1) / 1e6 + "ms");
ResponseBody body = response.body();
if (body != null) {
Log.d("Retrofit", "响应体: " + body.string());
}
return response;
};
六、常见问题与解决方案
-
类型转换异常(ConversionException) :
- 原因:JSON 结构与目标类不匹配;
- 解决方案:使用
@SerializedName注解匹配字段,或自定义 Converter。
-
网络请求超时:
-
原因:OkHttpClient 超时时间设置过短;
-
解决方案:
java
OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(15, TimeUnit.SECONDS) .readTimeout(20, TimeUnit.SECONDS) .build();
-
-
RxJava 背压处理:
-
场景:大数据流时出现
MissingBackpressureException; -
解决方案:使用
Flowable并设置背压策略:java
.addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io())) // 接口返回Flowable @GET("data") Flowable<DataItem> getData(@Query("page") int page);
-
七、总结:Retrofit 的核心能力
Retrofit 的强大源于其灵活的架构设计:
-
解耦:将 HTTP 请求、类型转换、异步处理分离为独立模块;
-
可扩展:通过 Factory 模式支持自定义转换规则;
-
易用性:动态代理将复杂请求封装为接口调用。
掌握 Retrofit 的源码原理,不仅能解决日常开发问题,还能在此基础上定制更适合业务的网络框架,如添加请求签名、动态域名切换等高级功能。