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

我个人习惯给路径参数起个清晰的名字,别用 ab 这种。不然三个月后你自己都看不懂。

@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 的核心脉络:

Retrofit 核心 RESTful 设计 注解体系 OkHttp 底层 @GET / @POST @Path / @Query @Body 接口定义 → 注解描述 → 自动生成 HTTP 请求 类型安全 · 协程友好 · 易于测试

避坑指南

最后分享几个我踩过的坑:

  • Base URL 记得以 / 结尾:比如 https://api.example.com/,不然路径拼接会出问题
  • 接口方法要加 suspend:配合协程时,别忘了在方法前加 suspend,否则没法在协程里调用
  • 响应体别用 ResponseBody:除非你真的需要原始数据,否则指定具体类型,让 Retrofit 帮你反序列化
  • 超时设置别忘:Retrofit 本身不设超时,得在 OkHttpClient 上配。我一般设连接超时 10 秒,读取超时 30 秒

好了,Retrofit 的核心概念就这些。下一节咱们会动手搭建一个完整的网络层,到时候这些注解都会用上。


公众号:蓝海资料掘金营,微信deep3321