第4章:Retrofit基本用法——定义接口、创建实例、发送请求
好了,聊完了Mock适配器能干什么,咱们得先打好基础。这一章,我带你完整走一遍Retrofit最核心的三个步骤。说白了,就是怎么把网络请求变成Java接口,怎么搭好Retrofit这个“发动机”,然后真正跑起来。
很多新手一上来就写代码,结果卡在接口定义和注解上。我觉得,先理清流程比什么都重要。先看下面这张图,你心里就有个谱了。
第一步:定义一个纯粹的接口
这是Retrofit最优雅的地方。你不用写任何实现类,只需要声明一个Java接口,然后在方法上贴几个注解就行了。
我个人习惯先把API的Response Model建好。比如一个用户对象User,一个文章对象Article。这些是基础。
public interface ApiService {
@GET("users/{id}")
Call<User> getUser(@Path("id") int userId);
@POST("users")
Call<User> createUser(@Body User user);
}
你看,@GET注解指定了相对路径,@Path动态替换URL里的{id}。@Body会把User对象自动转成JSON。
一个小技巧:接口里的方法名可以随便起,比如getUser、fetchUser都行,不影响请求地址。真正起作用的是注解里的URL和参数。
第二步:打造你的Retrofit实例
Retrofit实例是整个库的入口。你得告诉它:你的服务器根地址在哪,用什么来解析数据。我通常这么写:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
这里要小心:baseUrl必须以“/”结尾。为什么?我记得有一次没加,结果请求拼接出来的URL是错的,查了好久才发现。
Converter Factory是用来把JSON转成Java对象的。最常用的是Gson,也有Moshi、Jackson可选。我早期用Gson,后来发现Moshi对Kotlin更友好,但这里不展开。
第三步:生成接口代理,发送请求
有了Retrofit实例,调用它的create方法,就能拿到你之前写的接口的实现。这背后用的是Java动态代理,你不用关心细节。
ApiService apiService = retrofit.create(ApiService.class);
Call<User> call = apiService.getUser(123);
call对象不会立刻发网络请求。你得主动去触发它。有两种方式:
- 同步请求(execute):会阻塞当前线程,不能在主线程调用。适合后台线程。
- 异步请求(enqueue):在后台线程执行,回调在主线程。我建议绝大多数场景用这个。
// 异步请求,我最常用的方式
call.enqueue(new Callback<User>() {
@Override
public void onResponse(Call<User> call, Response<User> response) {
if (response.isSuccessful()) {
User user = response.body();
// 更新UI
} else {
// 处理错误状态码
}
}
@Override
public void onFailure(Call<User> call, Throwable t) {
// 网络异常,比如没网、超时
}
});
重点提醒:onResponse不意味着请求成功。它只代表服务器有响应了。你得检查response.isSuccessful()才能拿到200-299的状态码数据。我踩过这个坑——以为进了onResponse就没问题,结果从服务器拿到一个空对象。
关于注解的补充
除了@GET、@POST,还有几个常用的,我列个表给你看:
| 注解 | 用途 | 举例 |
|---|---|---|
| @Query | 拼接查询参数 | ?page=1 |
| @Field | 表单提交参数 | 配合@FormUrlEncoded |
| @Header | 静态请求头 | @Header("Authorization") |
| @Path | 替换URL占位符 | {id} → 123 |
注意:@Field不能在@GET方法上用,它只适用于@POST表单提交。我曾经把@GET和@Field混用,Gradle编译不报错,运行时却抛异常。所以一定要看清楚方法注解和参数注解的搭配。
完整示例跑一遍
现在我们把三个步骤串起来,写个完整的例子,去请求GitHub用户信息:
// 1. 定义接口
public interface GitHubService {
@GET("users/{username}")
Call<User> getUser(@Path("username") String username);
}
// 2. 创建Retrofit实例
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
// 3. 生成代理并发送请求
GitHubService service = retrofit.create(GitHubService.class);
Call<User> call = service.getUser("octocat");
call.enqueue(new Callback<User>() {
@Override
public void onResponse(Call<User> call, Response<User> response) {
if (response.isSuccessful()) {
User user = response.body();
System.out.println("用户名:" + user.login);
}
}
@Override
public void onFailure(Call<User> call, Throwable t) {
t.printStackTrace();
}
});
嗯,这就完成了从定义到请求的全流程。其实核心代码就那么几行。理解这个模式以后,不管多复杂的API,都是这样搭积木。
再强调一句,如果你只是跑本地测试而不想真正联网,就可以开始考虑Mock适配器了。下一章?哦不,其实你可以立刻用上面的代码接上Mock适配器测试。别急,后面我会专门讲。
好了,Retrofit的基本用法就说到这里。你先动手写几个接口感受一下,重点是理解接口注解和Retrofit Builder的配置。这玩意儿熟练了,后面搭建Mock适配器会顺手很多。