Retrofit 网络请求:类型安全的 HTTP 客户端

FreeGuideOnline 最新 2026-06-17

Retrofit 网络请求:类型安全的 HTTP 客户端 完整教程

Retrofit 是 Square 公司开源的一款 类型安全的 HTTP 客户端,广泛应用于 Android 和 Java 项目。它将 HTTP API 转化为 Java 接口,通过注解描述请求参数,配合数据转换器(如 Gson)自动将 JSON 解析为 Java 对象,极大简化网络请求的编码工作。无论你是刚接触移动开发,还是希望提升网络层健壮性,这篇教程都将带你从零掌握 Retrofit。


为什么选择 Retrofit?

  • 声明式 API:只需定义接口,无需手动处理 URL、请求头、序列化。
  • 类型安全:请求和响应都映射为具体的 Java/Kotlin 类,编译期即可发现拼写或结构错误。
  • 无缝集成:支持 OkHttp 拦截器、RxJava、Kotlin 协程、LiveData 等现代编程范式。
  • 高度可定制:可插入不同的 JSON 转换器、Call 适配器、数据格式(XML、Protobuf)。
  • 社区活跃:稳定、文档丰富,几乎是 Android 网络库的事实标准。

环境配置与依赖

在你的模块级 build.gradle(或 build.gradle.kts)中添加以下依赖:

dependencies {
    // Retrofit 核心库
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    // Gson 转换器(用于 JSON 自动解析)
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
    // 若使用 Kotlin 协程,还需要 adapter
    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.9.0' // 如使用 RxJava
}

注意:Retrofit 2 依赖于 OkHttp,Gson 转换器依赖于 Gson,这些传递性依赖会自动导入。


快速上手:构建第一个网络请求

假设我们有一个接口 https://api.example.com/users/1 返回如下 JSON:

{
  "id": 1,
  "name": "John Doe",
  "email": "john@example.com"
}

1. 定义数据模型

public class User {
    private int id;
    private String name;
    private String email;
    // 必须提供无参构造及 getter/setter(或使用 Lombok / Kotlin data class)
}

2. 定义 API 接口

public interface ApiService {
    @GET("users/{id}")
    Call<User> getUser(@Path("id") int userId);
}
  • @GET 指定 HTTP 方法和相对路径。
  • {id} 是占位符,由 @Path("id") 方法参数替换。

3. 创建 Retrofit 实例并发送请求

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://api.example.com/")
        .addConverterFactory(GsonConverterFactory.create())
        .build();

ApiService service = retrofit.create(ApiService.class);

// 异步执行
Call<User> call = service.getUser(1);
call.enqueue(new Callback<User>() {
    @Override
    public void onResponse(Call<User> call, Response<User> response) {
        if (response.isSuccessful()) {
            User user = response.body();
            // 使用 user 对象
        }
    }

    @Override
    public void onFailure(Call<User> call, Throwable t) {
        // 处理网络错误
    }
});

若需同步调用(慎用,可能阻塞主线程),使用 call.execute()


Retrofit 核心注解详解

请求方法注解

注解 说明
@GET HTTP GET
@POST HTTP POST
@PUT HTTP PUT
@DELETE HTTP DELETE
@HEAD HTTP HEAD
@PATCH HTTP PATCH
@OPTIONS HTTP OPTIONS
@HTTP 自定义方法

示例:@HTTP(method = "DELETE", path = "users/{id}", hasBody = true)

URL 操控

  • @Url:动态指定完整 URL(慎用,会覆盖 baseUrl)。
  • @Path:替换路径中的占位符。
  • @Query:添加查询参数 ?page=1
  • @QueryMap:将 Map 转为查询参数。
@GET("users")
Call<List<User>> getUsers(@Query("page") int page, @Query("limit") int limit);

请求体与表单

  • @Body:将 Java 对象序列化为 JSON 作为请求体(通常用于 POST)。
  • @FormUrlEncoded + @Field:发送表单编码数据(application/x-www-form-urlencoded)。
  • @Multipart + @Part:上传文件或多部分数据。
@FormUrlEncoded
@POST("login")
Call<LoginResponse> login(@Field("username") String user, @Field("password") String pwd);

请求头

  • @Headers:静态请求头(方法或类级别)。
  • @Header:动态请求头,通过参数传入。
@Headers({
    "Accept: application/json",
    "Cache-Control: max-age=640000"
})
@GET("profile")
Call<User> getProfile(@Header("Authorization") String token);

数据转换器

Retrofit 默认只处理 ResponseBody,需添加转换器自动解析。常用转换器:

  • Gsoncom.squareup.retrofit2:converter-gson
  • Moshicom.squareup.retrofit2:converter-moshi
  • Jacksoncom.squareup.retrofit2:converter-jackson
  • Simple XMLcom.squareup.retrofit2:converter-simplexml
  • Scalars(处理原始字符串):com.squareup.retrofit2:converter-scalars

添加方式:在构建 Retrofit 时使用 .addConverterFactory(GsonConverterFactory.create())


响应处理与 Call Adapter

基础 Response 对象

Call<T> 的异步回调返回 Response<T>,包含:

  • isSuccessful():状态码 200~299 时为 true。
  • body():解析后的对象。
  • errorBody():错误时服务器可能返回的响应体。
  • code()message():HTTP 状态码和消息。

结合 Kotlin 协程

最新版 Retrofit 原生支持 suspend 函数。只需在接口中将返回类型改为对象,并添加协程适配器:

@GET("users/{id}")
suspend fun getUser(@Path("id") id: Int): User

无需 enqueue,直接在协程作用域内调用,异常自动抛出非成功响应。

其他 Call Adapter

替换默认 CallObservableLiveData 等:

.addCallAdapterFactory(RxJava2CallAdapterFactory.create())

然后接口方法可返回 Observable<User>Flowable<User>


OkHttp 拦截器与日志

Retrofit 基于 OkHttp,可通过 OkHttpClient 添加拦截器。

添加日志拦截器

首先引入依赖 com.squareup.okhttp3:logging-interceptor,然后:

HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);

OkHttpClient client = new OkHttpClient.Builder()
        .addInterceptor(logging)
        .build();

Retrofit retrofit = new Retrofit.Builder()
        .client(client)
        // ... 其他配置
        .build();

通用请求头拦截器

Interceptor headerInterceptor = chain -> {
    Request original = chain.request();
    Request request = original.newBuilder()
            .header("Authorization", "Bearer " + getToken())
            .header("Accept", "application/json")
            .build();
    return chain.proceed(request);
};
clientBuilder.addInterceptor(headerInterceptor);

最佳实践与进阶技巧

1. 单例模式

Retrofit 实例创建开销较大,应全局复用。通常将 ApiService 也作为单例提供。

public class RetrofitClient {
    private static Retrofit retrofit = null;
    public static Retrofit getClient(String baseUrl) {
        if (retrofit == null) {
            OkHttpClient client = new OkHttpClient.Builder()
                    .connectTimeout(30, TimeUnit.SECONDS)
                    .readTimeout(30, TimeUnit.SECONDS)
                    .build();
            retrofit = new Retrofit.Builder()
                    .baseUrl(baseUrl)
                    .client(client)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }
        return retrofit;
    }
}

2. 统一错误处理

封装一个网络请求工具类,在 onResponse 中统一处理状态码和异常转译:

  • response.code() == 401,跳转登录页。
  • 将 HTTP 错误封装为自定义异常(如 ApiException),结合 LiveData 或 StateFlow 暴露给 UI。

3. 超时与缓存

通过 OkHttpClient.Builder 设置:

.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(15, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS)
.cache(new Cache(cacheDir, 10 * 1024 * 1024)) // 10MB 缓存

4. 结合 ViewModel + Kotlin Coroutines

class UserViewModel : ViewModel() {
    private val _user = MutableLiveData<User>()
    val user: LiveData<User> = _user

    fun fetchUser(id: Int) {
        viewModelScope.launch {
            try {
                val result = RetrofitClient.apiService.getUser(id)
                _user.value = result
            } catch (e: Exception) {
                // 显示错误
            }
        }
    }
}

5. 动态 BaseUrl(多环境)

使用 @Url 注解或自定义拦截器动态替换 baseUrl。也可在构建 Retrofit 实例时根据 flavor 设置不同的 baseUrl。


总结

Retrofit 通过接口注解的方式将 RESTful API 描述得清晰直观,配合类型安全的转换器与丰富的请求适配能力,大幅降低了网络层的开发与维护成本。从简单的 GET 请求到复杂的多部分上传,从同步调用到协程流,它都能优雅应对。现在,你可以立即动手,将 Retrofit 集成到你的项目中,体验“声明式”网络编程的畅快感。

继续学习:深入了解 OkHttp 拦截器链Kotlin 协程异常处理,让你的网络层更加健壮。