1. Retrofit 核心原理解析

本章深入 Retrofit 的底层运行机制,涵盖动态代理、注解解析、CallAdapter 与 Converter 的协作模式,以及一次完整 HTTP 请求从接口定义到网络响应的执行流程。掌握这些原理是后续进行高级配置、性能优化和错误排查的基础。

1.1 整体架构流程

Retrofit 本质上是一个接口驱动的 HTTP 客户端封装库:开发者只定义 Java 接口与方法注解,Retrofit 在运行时通过 动态代理 生成代理对象,调用时解析注解、构建请求、交由 OkHttp 执行,再通过 Converter 反序列化响应体,最后通过 CallAdapter 适配为所需返回类型(如 Call、LiveData、RxJava 等)。

核心思想: Retrofit 将网络请求的声明(注解)与执行(OkHttp)解耦,使开发者只需关注业务接口,无需关心 HTTP 通信细节。
Retrofit 请求与响应核心流程 @GET /users 动态代理 注解解析器 Method & Annotation URL / 参数组装 OkHttp Call Converter JSON → User GsonConverter CallAdapter Call → LiveData RxJava / Kotlin onResponse 回调/观察者 主线程分发 关键节点说明 ① 动态代理:拦截接口调用,收集方法注解与参数。 ② 注解解析:提取 HTTP 方法、路径、查询参数、请求体等。 ③ Converter:序列化请求体 / 反序列化响应体;CallAdapter:转换 Call 形态。

1.2 动态代理机制

Retrofit 通过 java.lang.reflect.Proxy 为每个用户定义的接口生成代理对象。当调用任意方法时,代理的 invoke() 方法被触发,其中包含了完整的方法元数据。

// Retrofit 内部简化示意(非实际源码)
public class Retrofit {
    public <T> T create(final Class<T> service) {
        return (T) Proxy.newProxyInstance(
            service.getClassLoader(),
            new Class<?>[] { service },
            new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) {
                    // 1. 解析方法上的注解(@GET、@POST 等)
                    // 2. 解析参数注解(@Query、@Body、@Path 等)
                    // 3. 构建 ServiceMethod 对象
                    // 4. 通过 OkHttp 执行或返回 Call
                }
            }
        );
    }
}
关键点: 每次调用接口方法都会触发代理的 invoke,但 Retrofit 内部会缓存解析后的 ServiceMethod,避免重复注解解析开销。

1.3 注解解析与参数绑定

Retrofit 支持多种 HTTP 方法注解(@GET、@POST、@PUT、@DELETE、@PATCH、@HEAD、@OPTIONS)和参数注解。注解处理器在第一次调用时解析并缓存为 ServiceMethod。

注解类别常用注解作用
HTTP 方法@GET、@POST、@PUT、@DELETE指定请求方法
URL 占位@Path("id")替换路径中的 {id}
查询参数@Query("page")追加 ?page=value
请求体@Body序列化对象为请求 body
请求头@Header("Authorization")添加请求 Header
表单字段@Field("name")配合 @FormUrlEncoded 使用
多部分@Part("file")配合 @Multipart 上传文件
// 示例:接口定义
public interface GithubService {
    @GET("users/{user}/repos")
    Call<List<Repo>> listRepos(
        @Path("user") String user,
        @Query("sort") String sort,
        @Query("per_page") int perPage
    );
}

1.4 CallAdapter 与 Converter 协作

CallAdapter 负责将 OkHttp 的 Call 转换为开发者期望的返回类型(如 LiveData、RxJava Observable、Kotlin suspend 等)。Converter 负责将网络数据流与 Java 对象互相转换。

// 添加 Gson Converter 和 RxJava CallAdapter
Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .addConverterFactory(GsonConverterFactory.create())
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    .build();
执行顺序: 响应流先经过 Converter 反序列化为 Java 对象,再经过 CallAdapter 包装为返回类型。Retrofit 内部按添加顺序遍历工厂,直到找到能处理的适配器。

1.5 请求与响应完整流程

  1. 创建代理:retrofit.create(Api.class) 返回动态代理实例。
  2. 方法调用:调用接口方法(如 api.listRepos("octocat", "updated", 10))。
  3. 解析 & 缓存:ServiceMethod 解析注解、参数,生成 RequestBuilder。
  4. 构建 OkHttp Request:组装 URL、Header、Body、Query 等。
  5. 执行网络请求:OkHttp 发起同步或异步 HTTP 请求。
  6. 获取原始 Response:OkHttp 返回 ResponseBody(字节流)。
  7. Converter 反序列化:将 ResponseBody 转为 List<Repo> 等 Java 对象。
  8. CallAdapter 转换:将 Call<List<Repo>> 转为 Observable<List<Repo>> 或 LiveData 等。
  9. 返回/回调:最终结果通过回调或观察者传递到调用方。

1.6 常见错误与调优建议

常见错误:
  • 未添加 Converter 工厂导致 java.lang.IllegalArgumentException: Unknown class as response type。
  • 接口路径未以 / 开头导致 URL 拼接错误。
  • 使用 @QueryMap 时 Map 的 value 类型非 String 导致序列化异常。
  • CallAdapter 工厂顺序错误,导致类型不匹配。
// 错误示例:缺少 Converter
Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.example.com/")
    .build();  // 没有加 addConverterFactory,请求时会抛出异常
稳定性优化: 将 Retrofit 实例设为单例;对 OkHttpClient 的超时、重试、缓存进行统一配置;使用自定义 CallAdapter 统一错误处理和线程切换。

1.7 本章小结