Retrofit 网络请求:类型安全的 HTTP 客户端
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,需添加转换器自动解析。常用转换器:
- Gson:
com.squareup.retrofit2:converter-gson - Moshi:
com.squareup.retrofit2:converter-moshi - Jackson:
com.squareup.retrofit2:converter-jackson - Simple XML:
com.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
替换默认 Call 为 Observable、LiveData 等:
.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 协程异常处理,让你的网络层更加健壮。