Retrofit 核心概念:从入门到实战
说实话,Retrofit 是我在 Android 开发中用得最顺手的网络库。没有之一。
记得我刚接触它的时候,还在用 OkHttp 手写各种请求封装。那时候每个接口都要写一大坨代码,解析 JSON 更是噩梦。后来团队引入 Retrofit,我才发现——原来网络请求可以这么优雅。
这一节,咱们就聊聊 Retrofit 到底是什么,以及它的核心注解怎么用。
什么是 Retrofit?
Retrofit 是 Square 公司出品的一个类型安全的 HTTP 客户端。说白了,它就是 OkHttp 的「高级封装」。
你想想看,OkHttp 本身已经很强大了,但每次请求你都得手动构建 Request、处理 Response、解析数据。Retrofit 把这些重复劳动全干了——你只需要定义一个接口,加上注解,它就自动帮你搞定一切。
核心思想:Retrofit 把 HTTP API 转化成了 Java/Kotlin 接口调用。你调一个方法,它就发一个请求。
我个人的习惯是,每个业务模块对应一个 Retrofit 接口文件。比如用户模块一个 UserApi,订单模块一个 OrderApi。这样结构清晰,也好维护。
RESTful API 设计原则
要玩转 Retrofit,你得先理解 RESTful。因为 Retrofit 的注解设计,就是照着 RESTful 风格来的。
RESTful 不是什么高深理论,它只是一套约定。我总结下来就几条:
- 资源用名词表示:比如
/users、/orders,别用动词 - HTTP 方法代表操作:GET 查、POST 增、PUT 改、DELETE 删
- 状态码传达结果:200 成功、201 创建成功、404 没找到、500 服务器炸了
- 无状态:每次请求都带全所需信息,服务端不存客户端状态
举个例子,一个用户系统的 RESTful 接口大概长这样:
| HTTP 方法 | 路径 | 含义 |
|---|---|---|
| GET | /users | 获取用户列表 |
| GET | /users/{id} | 获取单个用户 |
| POST | /users | 创建新用户 |
| PUT | /users/{id} | 更新用户信息 |
| DELETE | /users/{id} | 删除用户 |
我曾经在一个项目里见过有人把 GET 请求写成 /getUserInfo,POST 写成 /createNewUser。嗯,不能说错,但维护起来真的很痛苦。后来重构时全改成了 RESTful 风格,接口文档都清爽多了。
Retrofit 注解详解
注解是 Retrofit 的灵魂。你写接口时,80% 的工作就是贴注解。咱们挑最常用的几个来讲。
@GET 和 @POST
这两个注解指定 HTTP 方法。用法很简单:
interface UserApi {
@GET("users")
suspend fun getUsers(): List<User>
@POST("users")
suspend fun createUser(@Body user: User): User
}
注意看,路径 "users" 是相对路径。Base URL 在创建 Retrofit 实例时指定。我一般把 Base URL 写在 BuildConfig 里,方便切换测试环境和生产环境。
小技巧:路径开头不要加 /,除非你想覆盖 Base URL 的路径部分。我踩过这个坑,加了个斜杠结果请求地址全乱了。
@Path:动态路径参数
当路径中有可变部分时,用 @Path 来替换。比如获取某个用户的详情:
@GET("users/{id}")
suspend fun getUser(@Path("id") userId: Long): User
这里 {id} 是占位符,运行时会被 userId 的值替换。如果传 10086,实际请求就是 GET /users/10086。
我个人习惯给路径参数起个清晰的名字,别用 a、b 这种。不然三个月后你自己都看不懂。
@Query:查询参数
查询参数就是 URL 问号后面的东西。比如分页、搜索关键词:
@GET("users")
suspend fun getUsers(
@Query("page") page: Int,
@Query("size") size: Int = 20
): List<User>
调用 getUsers(1) 会生成 GET /users?page=1&size=20。
这里有个细节:@Query 的参数可以是可空的。如果传 null,Retrofit 会自动忽略这个参数,不会拼到 URL 里。这个特性在条件查询时特别好用。
注意:如果参数是集合类型,比如 List<Int>,Retrofit 会生成多个同名参数。比如 @Query("id") ids: List<Int> 传 [1,2,3],结果就是 ?id=1&id=2&id=3。后端得支持这种格式才行。
@Body:请求体
POST 和 PUT 请求通常需要携带数据。用 @Body 注解标记参数,Retrofit 会自动把它序列化成 JSON(配合 Gson 或 Moshi):
@POST("users")
suspend fun createUser(@Body user: User): User
这里 User 对象会被转成 JSON 放在请求体里。我建议请求体对象用 data class,配合 Kotlin 的默认参数,能省不少代码。
曾经有个同事把 @Body 和 @Field 搞混了,结果后端一直收不到参数。嗯,@Body 是传 JSON 对象的,@Field 是表单提交用的,别弄反了。
核心知识体系
下面这张图帮你理清 Retrofit 的核心脉络:
避坑指南
最后分享几个我踩过的坑:
- Base URL 记得以
/结尾:比如https://api.example.com/,不然路径拼接会出问题 - 接口方法要加
suspend:配合协程时,别忘了在方法前加suspend,否则没法在协程里调用 - 响应体别用
ResponseBody:除非你真的需要原始数据,否则指定具体类型,让 Retrofit 帮你反序列化 - 超时设置别忘:Retrofit 本身不设超时,得在 OkHttpClient 上配。我一般设连接超时 10 秒,读取超时 30 秒
好了,Retrofit 的核心概念就这些。下一节咱们会动手搭建一个完整的网络层,到时候这些注解都会用上。