第4章:Retrofit基本用法——定义接口、创建实例、发送请求

好了,聊完了Mock适配器能干什么,咱们得先打好基础。这一章,我带你完整走一遍Retrofit最核心的三个步骤。说白了,就是怎么把网络请求变成Java接口,怎么搭好Retrofit这个“发动机”,然后真正跑起来。

很多新手一上来就写代码,结果卡在接口定义和注解上。我觉得,先理清流程比什么都重要。先看下面这张图,你心里就有个谱了。

Retrofit基本用法流程 定义接口(Interface) @GET / @POST 注解 创建Retrofit实例 设置baseUrl + Converter 生成接口代理 retrofit.create(...) 定义请求方法 @GET("user/{id}") 调用方法 → 得到Call Call<User> call 执行Call(同步/异步) enqueue / execute 核心流程 接口定义 → 创建实例 → 生成代理 → 定义请求 → 发送请求 → 处理响应

第一步:定义一个纯粹的接口

这是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适配器会顺手很多。