Retrofit — 是由 Square 公司开发的适用于 Android 和 Kotlin 的类型化 HTTP 客户端。该库允许通过注解将 REST API 转换为 Java 或 Kotlin 接口。根据 Square, 2025 的数据,Retrofit 被数千个应用程序用作处理 HTTP 请求的标准工具。
要点
Retrofit — 是由 Square 公司开发的用于 Android 平台上与 REST API 进行类型化交互的库。它通过带有注解的 Java 或 Kotlin 接口提供了描述 HTTP 请求的声明式方法,使开发者完全无需手动解析 JSON 和管理 HTTP 连接。
该库于 2013 年作为 AsyncTask 和 HttpURLConnection 等繁琐解决方案的替代品出现。到 2025 年,Retrofit 凭借其简单性和类型安全性仍然是 Android 应用程序中网络通信的事实标准。根据 JetBrains Developer Ecosystem 2024 调查,超过 65% 的 Android 开发者在商业项目中使用 Retrofit。
Retrofit 与同类产品的主要区别 — 声明式方法:开发者描述要做什么(调用哪个端点、传递哪些参数),而不是如何做(如何打开连接、如何读取 InputStream、如何解析 JSON)。与手动使用 HttpURLConnection 相比,这将样板代码量减少了 60–70%。
工作原理 — Retrofit 基于 Java 动态代理。当开发者调用带有注解的接口方法时,Retrofit 通过 Proxy.newProxyInstance 机制拦截调用并将其转换为 HTTP 请求。整个过程在运行时发生,无需在编译阶段生成代码。
创建 Retrofit.Builder 实例时,指定基本 URL 和转换器工厂。Builder 配置 OkHttpClient — 设置超时、拦截器、连接池和缓存。create(Class) 方法生成接口的实现,返回一个可以像普通类一样调用的代理对象。
请求执行链如下:注解提取 HTTP 方法,参数替换到 URL 或请求体中,转换器序列化请求体,OkHttp 执行请求,转换器反序列化响应,结果以指定类型返回。每个阶段都是隔离的,可以替换为自定义实现,例如将 OkHttpClient 替换为 MockWebServer 进行测试,或在 API 更改时更换转换器。
重要特性 — Retrofit 不直接支持数据流传输。对于流式传输,使用 OkHttp ResponseBody 作为接口方法的返回类型。Retrofit 也不自动管理请求取消 — 要取消需要保存对 Call 的引用并调用 cancel()。在 Kotlin 中使用 suspend 函数时,请求取消会在父协程取消时自动发生。
Call<T> — 是代表单个 HTTP 请求的对象。执行后(execute 或 enqueue),Call 不能重复使用 — 重复请求需要通过调用接口方法创建新的 Call。这可以防止意外发送同一请求两次,从而避免服务器上操作的重复。
在 Kotlin 中,使用 suspend 函数代替 Call,这些函数自动管理请求的生命周期。Retrofit 自行将执行切换到 Dispatchers.IO 并将结果返回到协程。与使用 Call 和 Callback 的版本相比,这简化了代码 30–40%。
注解 — 是 Retrofit 中配置 HTTP 请求的主要机制。每个注解对应一个标准 HTTP 方法,并接受到端点的相对路径。Retrofit 支持 GET、POST、PUT、DELETE、PATCH、HEAD 和 OPTIONS。
| 注解 | HTTP 方法 | 用途 |
|---|---|---|
| @GET | GET | 从服务器获取数据 |
| @POST | POST | 创建新资源 |
| @PUT | PUT | 完全更新资源 |
| @DELETE | DELETE | 删除资源 |
| @PATCH | PATCH | 部分更新资源 |
@Path 替换 URL 段中的值:@Path(id) Int id 替换路径中的 {id}。@Query 添加查询参数:@Query(page) Int page 变成 ?page=5。@Body 通过所选转换器自动序列化后在请求体中传递对象。@Header 和 @Headers 管理 HTTP 标头 — 静态或动态。
结合这些注解,可以描述任何 REST 端点。例如,对于端点 POST /api/users/{id}/posts?limit=10,需要 @POST、用于 id 的 @Path、用于 limit 的 @Query 和用于传递对象的 @Body。Retrofit 会自动组装正确的 HTTP 请求。此外还支持 @Url(动态 URL)、@Field(表单编码主体)、@Part 和 @PartMap 用于带文件的多部分请求。
让我们看一个实际示例 — 用于 GitHub API 的接口。创建一个 Kotlin 接口,其中包含获取存储库列表的方法。Data class Repo 描述 JSON 响应的结构。
data class Repo(
val name: String,
val description: String?,
val stargazersCount: Int,
val forksCount: Int
)
interface GitHubApi {
@GET("users/{user}/repos")
suspend fun getRepos(
@Path("user") user: String,
@Query("sort") sort: String = "updated"
): List<Repo>
}
描述接口后,通过 Builder 创建 Retrofit 实例。基本 URL、转换器和 OkHttpClient 配置一次,并通过依赖注入重复使用。
val retrofit = Retrofit.Builder()
.baseUrl("https://api.github.com/")
.addConverterFactory(GsonConverterFactory.create())
.client(OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.build())
.build()
val api = retrofit.create(GitHubApi::class.java)
为了灵活处理HTTP 状态,请使用 Response<T> 包装器。它提供对响应代码、标头和主体的访问,而不会在 4xx 和 5xx 错误时抛出异常。这允许在没有 try-catch 的情况下处理 404 和 500。
interface GitHubApi {
@GET("users/{user}/repos")
suspend fun getRepos(
@Path("user") user: String
): Response<List<Repo>>
}
val response = api.getRepos("octocat")
if (response.isSuccessful) {
println(response.body()?.size)
} else {
Log.e("API", "错误:${response.code()}")
}
转换器 — 是 Retrofit 中负责将对象转换为 HTTP 主体和反向转换的组件。Retrofit 不将序列化内置于核心中 — 而是通过 Converter.Factory 使用模块化方法,允许连接任何序列化库。
最流行的转换器 — 基于 Gson 库的 Google GsonConverterFactory。适用于大多数项目,支持自定义 TypeAdapter 和 JsonDeserializer。然而,Gson 使用反射且不考虑 Kotlin 的空安全性,这可能导致在意外空字段时出现 NPE。
替代方案 — Square 的 MoshiConverterFactory:对类型更严格,对 Kotlin 有更好的支持(空安全性、默认值)且无反射。对于纯 Kotlin 项目,最佳选择是 Kotlinx Serialization Converter,它在编译阶段基于 @Serializable 注解工作。它不使用反射,支持密封类、默认值和多平台。
转换器的选择影响性能和类型安全性。未经自定义配置的 Gson 可能将 null 反序列化为 Kotlin 的非空字段,在访问时导致 NPE。Moshi 通过 @Json(name) 注解和 failOnUnknown 解决此问题。Kotlinx Serialization 最安全 — 在编译阶段生成代码,完全消除运行时类型错误。
在 suspend 函数中缺乏 HTTP 错误处理 — 最常见的问题。如果服务器返回 4xx 或 5xx,Retrofit 会抛出 HttpException。没有 try-catch,应用程序将崩溃。使用 Response<T> 作为返回类型可以解决此问题,允许在访问 body 之前检查 isSuccessful。
缓存配置错误 导致流量过多。Retrofit 本身不缓存响应 — 此任务由 OkHttpClient 通过 Cache 解决。没有缓存,每个请求都会完全执行,即使数据没有改变。在 OkHttpClient 中添加 10 MB 的缓存可将重复请求相同信息的流量减少 40–60%。
为每个请求创建 Retrofit — 初学者的常见错误。Retrofit.Builder 是一项资源密集型操作,包括在运行时生成代理类。正确的做法是创建一个 Retrofit 实例并通过 DI 框架重复使用。Hilt、Koin 或 Dagger 为整个应用程序提供单例 Retrofit 实例,从而节省内存并加快请求速度。
忽略用于授权的拦截器 — 第四个问题。无需手动在每个调用中添加 Authorization 标头,而是在 OkHttpClient 中配置全局拦截器。拦截器拦截每个请求,添加 Bearer 令牌,而 Authenticator 处理 401 响应,自动刷新令牌并使用新标头重复请求。这集中了身份验证逻辑。
常见问题
Retrofit — 是 OkHttp 之上的一个层,通过注解提供声明式 API。OkHttp — 是直接处理 Request 和 Response 的低级 HTTP 客户端。Retrofit 使用 OkHttp 作为传输,简化了类型化、序列化和响应处理。
对于 Java 项目 — GsonConverterFactory。对于使用 Moshi 的 Kotlin — MoshiConverterFactory(类型更安全)。纯 Kotlin 的最佳选择 — Kotlinx Serialization Converter。无需反射即可工作,支持密封类和默认值。
是的,从版本 2.6.0 开始,Retrofit 支持suspend 函数。将方法声明为 suspend,Retrofit 将在 Dispatchers.IO 上执行请求并将结果返回到协程。无需使用 Call 和 enqueue — 代码变为顺序执行。
授权通过 OkHttp 的拦截器添加。在 intercept() 中添加 Authorization 标头。对于动态令牌,使用 OkHttp 的 Authenticator — 它拦截 401 响应并自动刷新令牌,使用新标头重复请求。
不能 — Retrofit 始终使用 OkHttp 作为传输层。OkHttpClient 通过 Builder.client() 传递,并管理超时、拦截器、缓存和连接池。没有 OkHttp,Retrofit 无法执行任何请求。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。