教程来自Claude问答:
请给我开源库Retrofit的使用教程,按从入门到精通的方式由浅入深的给我讲解,并给予相应的示例代码方便理解,请使用Kotlin语言。
好的!下面我将为你提供一份从入门到精通的 Retrofit 完整教程。

第一章:入门基础 --- 什么是 Retrofit?
Retrofit 是 Square 公司开源的一个 Android/Java 类型安全的 HTTP 客户端库 。它将 HTTP API 定义为 Kotlin 接口,并通过注解和动态代理自动生成实现代码,极大简化网络请求逻辑。下面我们先用一张架构图建立整体认知。


1.1 添加依赖
在 build.gradle.kts(Kotlin DSL)中添加:
kotlin
kotlin
dependencies {
// Retrofit 核心
implementation("com.squareup.retrofit2:retrofit:2.11.0")
// JSON 转换器(Gson / Moshi / kotlinx.serialization 三选一)
implementation("com.squareup.retrofit2:converter-gson:2.11.0")
// 或 Moshi(更推荐 Kotlin 项目)
implementation("com.squareup.retrofit2:converter-moshi:2.11.0")
// Kotlin 协程支持
implementation("com.squareup.retrofit2:adapter-rxjava3:2.11.0") // RxJava(可选)
// OkHttp 日志拦截器(调试用)
implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")
}
别忘了 AndroidManifest 中声明网络权限:
xml
xml
<uses-permission android:name="android.permission.INTERNET" />
第二章:核心用法 --- 定义 API 接口
2.1 创建数据模型
kotlin
kotlin
// 数据类自动映射 JSON 字段
data class User(
val id: Int,
val name: String,
val email: String,
val username: String
)
data class Post(
val id: Int,
val userId: Int,
val title: String,
val body: String
)
// 创建 POST 请求时的请求体
data class CreatePostRequest(
val title: String,
val body: String,
val userId: Int
)
2.2 定义 API 接口(核心概念)
kotlin
kotlin
import retrofit2.http.*
import retrofit2.Call
import retrofit2.Response
interface ApiService {
// ─── GET 请求 ──────────────────────────────────
// 获取用户列表
@GET("users")
fun getUsers(): Call<List<User>>
// 路径参数:{id} 对应 @Path("id")
@GET("users/{id}")
fun getUserById(@Path("id") userId: Int): Call<User>
// 查询参数:?_page=1&_limit=10
@GET("posts")
fun getPosts(
@Query("_page") page: Int,
@Query("_limit") limit: Int
): Call<List<Post>>
// 多个查询参数 Map
@GET("posts")
fun searchPosts(@QueryMap params: Map<String, String>): Call<List<Post>>
// ─── POST 请求 ─────────────────────────────────
// 请求体(JSON)
@POST("posts")
fun createPost(@Body request: CreatePostRequest): Call<Post>
// 表单提交
@FormUrlEncoded
@POST("login")
fun login(
@Field("username") username: String,
@Field("password") password: String
): Call<User>
// ─── PUT / PATCH / DELETE ──────────────────────
@PUT("posts/{id}")
fun updatePost(
@Path("id") postId: Int,
@Body post: Post
): Call<Post>
@PATCH("posts/{id}")
fun patchPost(
@Path("id") postId: Int,
@Body fields: Map<String, String>
): Call<Post>
@DELETE("posts/{id}")
fun deletePost(@Path("id") postId: Int): Call<Response<Unit>>
// ─── 自定义请求头 ──────────────────────────────
@Headers("Cache-Control: max-age=640000")
@GET("users")
fun getUsersWithCache(): Call<List<User>>
// 动态 Header
@GET("protected/data")
fun getProtectedData(@Header("Authorization") token: String): Call<String>
}
2.3 创建 Retrofit 实例
kotlin
kotlin
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
object RetrofitClient {
private const val BASE_URL = "https://jsonplaceholder.typicode.com/"
// OkHttp 日志拦截器(仅 Debug 模式开启)
private val loggingInterceptor = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}
private val okHttpClient = OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build()
private val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()
// 懒加载单例
val apiService: ApiService by lazy {
retrofit.create(ApiService::class.java)
}
}
2.4 发起同步 / 异步请求
kotlin
kotlin
class MainActivity : AppCompatActivity() {
private val api = RetrofitClient.apiService
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// ── 异步请求(推荐)──────────────────────────
api.getUsers().enqueue(object : Callback<List<User>> {
override fun onResponse(call: Call<List<User>>, response: Response<List<User>>) {
if (response.isSuccessful) {
val users = response.body()
// response.code() == 200
// response.headers() 获取响应头
users?.forEach { println(it.name) }
} else {
// 处理 HTTP 错误(4xx / 5xx)
val errorBody = response.errorBody()?.string()
println("Error ${response.code()}: $errorBody")
}
}
override fun onFailure(call: Call<List<User>>, t: Throwable) {
// 网络错误、超时等
println("Network Error: ${t.message}")
}
})
// ── 同步请求(不能在主线程)─────────────────
Thread {
try {
val response = api.getUserById(1).execute()
if (response.isSuccessful) {
println(response.body()?.name)
}
} catch (e: IOException) {
println("IO Error: ${e.message}")
}
}.start()
}
}
第三章:进阶功能
3.1 OkHttp 拦截器
拦截器是 Retrofit 最强大的扩展点,可以统一处理 Token、加密、日志等。
kotlin
kotlin
// ── 认证拦截器:自动添加 Authorization Header ──
class AuthInterceptor(private val tokenProvider: () -> String) : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val originalRequest = chain.request()
val authenticatedRequest = originalRequest.newBuilder()
.header("Authorization", "Bearer ${tokenProvider()}")
.header("Content-Type", "application/json")
.build()
return chain.proceed(authenticatedRequest)
}
}
// ── Token 刷新拦截器(401 自动续签)──────────────
class TokenRefreshInterceptor : Authenticator {
override fun authenticate(route: Route?, response: Response): Request? {
// 如果已经重试过了,放弃
if (response.request.header("Retry-Token") != null) return null
// 同步刷新 Token(这里简化演示)
val newToken = refreshTokenSynchronously() ?: return null
return response.request.newBuilder()
.header("Authorization", "Bearer $newToken")
.header("Retry-Token", "true")
.build()
}
private fun refreshTokenSynchronously(): String? {
// 实际项目中调用刷新接口
return "new_access_token"
}
}
// ── 构建带拦截器的 OkHttpClient ──────────────────
val client = OkHttpClient.Builder()
.addInterceptor(AuthInterceptor { UserPrefs.getToken() })
.authenticator(TokenRefreshInterceptor())
.addInterceptor(HttpLoggingInterceptor().apply {
level = if (BuildConfig.DEBUG) {
HttpLoggingInterceptor.Level.BODY
} else {
HttpLoggingInterceptor.Level.NONE
}
})
.build()
3.2 文件上传(Multipart)
kotlin
kotlin
interface FileUploadService {
// 单文件上传
@Multipart
@POST("upload")
fun uploadFile(
@Part file: MultipartBody.Part,
@Part("description") description: RequestBody
): Call<UploadResponse>
// 多文件上传
@Multipart
@POST("upload/multiple")
fun uploadMultipleFiles(
@PartMap parts: Map<String, @JvmSuppressWildcards RequestBody>
): Call<UploadResponse>
}
// 使用示例
fun uploadImage(filePath: String) {
val file = File(filePath)
// 构建 RequestBody
val requestFile = file.asRequestBody("image/jpeg".toMediaTypeOrNull())
// 构建 MultipartBody.Part,"file" 是后端接收的字段名
val body = MultipartBody.Part.createFormData("file", file.name, requestFile)
// 描述信息
val description = "My upload".toRequestBody("text/plain".toMediaTypeOrNull())
RetrofitClient.apiService.uploadFile(body, description)
.enqueue(object : Callback<UploadResponse> {
override fun onResponse(...) { /* 处理结果 */ }
override fun onFailure(...) { /* 处理错误 */ }
})
}
3.3 下载文件(Streaming)
kotlin
kotlin
interface DownloadService {
// @Streaming 阻止 Retrofit 将整个文件读入内存
@Streaming
@GET
fun downloadFile(@Url fileUrl: String): Call<ResponseBody>
}
// 将 ResponseBody 写入磁盘
fun saveFile(body: ResponseBody, savePath: String): Boolean {
return try {
val file = File(savePath)
body.byteStream().use { inputStream ->
file.outputStream().use { outputStream ->
inputStream.copyTo(outputStream)
}
}
true
} catch (e: IOException) {
false
}
}
第四章:Kotlin 协程集成(现代推荐方式)
这是目前 Android 开发最推荐的方式,搭配 ViewModel + 协程效果最佳。
4.1 suspend 函数接口定义
kotlin
kotlin
// Retrofit 原生支持 suspend 函数,无需额外 Adapter
interface CoroutineApiService {
// 直接返回数据(失败时抛异常)
@GET("users")
suspend fun getUsers(): List<User>
// 返回 Response<T> 可以获取状态码、Header 等
@GET("users/{id}")
suspend fun getUserById(@Path("id") id: Int): Response<User>
@POST("posts")
suspend fun createPost(@Body request: CreatePostRequest): Post
@DELETE("posts/{id}")
suspend fun deletePost(@Path("id") id: Int): Response<Unit>
}
4.2 在 ViewModel 中使用
kotlin
kotlin
class UserViewModel(
private val api: CoroutineApiService = RetrofitClient.coroutineApiService
) : ViewModel() {
private val _uiState = MutableStateFlow<UiState<List<User>>>(UiState.Loading)
val uiState: StateFlow<UiState<List<User>>> = _uiState.asStateFlow()
fun loadUsers() {
viewModelScope.launch {
_uiState.value = UiState.Loading
_uiState.value = try {
val users = api.getUsers() // IO 在 Retrofit 内部处理
UiState.Success(users)
} catch (e: HttpException) {
// HTTP 错误(4xx, 5xx)
UiState.Error("Server error: ${e.code()}")
} catch (e: IOException) {
// 网络问题(无连接、超时)
UiState.Error("Network error: ${e.message}")
}
}
}
}
// 通用 UI 状态封装
sealed class UiState<out T> {
object Loading : UiState<Nothing>()
data class Success<T>(val data: T) : UiState<T>()
data class Error(val message: String) : UiState<Nothing>()
}
4.3 在 Activity/Fragment 中收集状态
kotlin
kotlin
class UserFragment : Fragment() {
private val viewModel: UserViewModel by viewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel.loadUsers()
// 收集 StateFlow
viewLifecycleOwner.lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.uiState.collect { state ->
when (state) {
is UiState.Loading -> showLoading()
is UiState.Success -> showUsers(state.data)
is UiState.Error -> showError(state.message)
}
}
}
}
}
}
第五章:最佳实践 --- Repository 封装模式
5.1 统一错误处理封装
kotlin
kotlin
// 网络请求结果封装
sealed class NetworkResult<out T> {
data class Success<T>(val data: T) : NetworkResult<T>()
data class Error(val code: Int, val message: String) : NetworkResult<Nothing>()
object Loading : NetworkResult<Nothing>()
}
// 扩展函数:安全执行网络请求
suspend fun <T> safeApiCall(apiCall: suspend () -> T): NetworkResult<T> {
return try {
NetworkResult.Success(apiCall.invoke())
} catch (e: HttpException) {
NetworkResult.Error(e.code(), e.message())
} catch (e: IOException) {
NetworkResult.Error(-1, "Network unavailable: ${e.message}")
} catch (e: Exception) {
NetworkResult.Error(-2, "Unknown error: ${e.message}")
}
}
5.2 Repository 层
kotlin
kotlin
class UserRepository(private val api: CoroutineApiService) {
suspend fun getUsers(): NetworkResult<List<User>> = safeApiCall {
api.getUsers()
}
suspend fun getUserById(id: Int): NetworkResult<User> = safeApiCall {
val response = api.getUserById(id)
if (response.isSuccessful) {
response.body() ?: throw HttpException(response)
} else {
throw HttpException(response)
}
}
suspend fun createPost(title: String, body: String): NetworkResult<Post> = safeApiCall {
api.createPost(CreatePostRequest(title, body, userId = 1))
}
}
第六章:高级技巧
6.1 动态 BaseUrl
kotlin
kotlin
// 接口中使用 @Url 覆盖 baseUrl
interface DynamicUrlService {
@GET
suspend fun fetchFromAbsoluteUrl(@Url absoluteUrl: String): ResponseBody
}
// 调用时传入完整 URL
api.fetchFromAbsoluteUrl("https://another-api.com/data/endpoint")
6.2 自定义 CallAdapter(Flow 支持)
kotlin
kotlin
// 让 Retrofit 直接返回 Flow<T>
// 依赖:com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter
// 或自己实现,更简洁的做法是在 Repository 用 flow { emit(safeApiCall{...}) }
fun <T> networkFlow(call: suspend () -> T): Flow<NetworkResult<T>> = flow {
emit(NetworkResult.Loading)
emit(safeApiCall { call() })
}.flowOn(Dispatchers.IO)
// ViewModel 中使用
val usersFlow: Flow<NetworkResult<List<User>>> = networkFlow { api.getUsers() }
6.3 请求缓存策略
kotlin
kotlin
// 配置 OkHttp Cache
val cacheDir = File(context.cacheDir, "http_cache")
val cache = Cache(cacheDir, 10L * 1024 * 1024) // 10 MB
val client = OkHttpClient.Builder()
.cache(cache)
.addNetworkInterceptor { chain ->
// 网络响应:缓存 60 秒
val response = chain.proceed(chain.request())
response.newBuilder()
.header("Cache-Control", "public, max-age=60")
.build()
}
.addInterceptor { chain ->
var request = chain.request()
// 无网络时使用缓存(最长 7 天)
if (!isNetworkAvailable(context)) {
request = request.newBuilder()
.header("Cache-Control", "public, only-if-cached, max-stale=${7 * 24 * 3600}")
.build()
}
chain.proceed(request)
}
.build()
6.4 使用 kotlinx.serialization(Kotlin 原生)
kotlin
kotlin
// 依赖
// implementation("com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0")
// implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3")
@Serializable
data class User(
val id: Int,
val name: String,
val email: String
)
val contentType = "application/json".toMediaType()
val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(Json.asConverterFactory(contentType))
.build()
学习路线总结

关键知识点速查
| 注解 | 作用 | 示例 |
|---|---|---|
@GET / @POST / @PUT / @DELETE |
请求方法 | @GET("users") |
@Path |
URL 路径参数 | @Path("id") id: Int |
@Query |
URL 查询参数 | @Query("page") page: Int |
@Body |
请求体 | @Body user: User |
@Header |
动态请求头 | @Header("Token") token: String |
@Multipart + @Part |
文件上传 | 见第三章 |
@Streaming |
流式下载 | 防止大文件 OOM |
@Url |
动态 URL | 覆盖 baseUrl |

Retrofit 的精髓在于注解,下面是所有常用注解的对照表:

最核心的建议 :在现代 Android 项目中,请务必使用 suspend 函数 + ViewModel + Repository 这套组合,配合 Hilt 做依赖注入,这是 2024 年 Android 官方推荐的标准架构。如果需要深入某个具体环节(比如 MockWebServer 单元测试、与 Paging3 结合分页加载、或 Hilt 集成),随时告诉我!