Retrofit #
一、Retrofit概述 #
Retrofit是Square公司开发的类型安全的HTTP客户端,基于OkHttp封装,通过注解定义API接口,使网络请求更加简洁。
1.1 Retrofit特点 #
- 类型安全
- 注解定义API
- 支持多种数据格式
- 支持协程
- 支持RxJava
1.2 添加依赖 #
kotlin
dependencies {
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")
}
二、基本使用 #
2.1 定义API接口 #
kotlin
interface ApiService {
@GET("users")
suspend fun getUsers(): List<User>
@GET("users/{id}")
suspend fun getUserById(@Path("id") id: Int): User
@GET("users")
suspend fun searchUsers(@Query("name") name: String): List<User>
@POST("users")
suspend fun createUser(@Body user: User): User
@PUT("users/{id}")
suspend fun updateUser(@Path("id") id: Int, @Body user: User): User
@DELETE("users/{id}")
suspend fun deleteUser(@Path("id") id: Int): Response<Unit>
}
2.2 创建Retrofit实例 #
kotlin
object RetrofitClient {
private const val BASE_URL = "https://api.example.com/"
private val loggingInterceptor = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}
private val okHttpClient = OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.connectTimeout(30, TimeUnit.SECONDS)
.build()
val apiService: ApiService by lazy {
Retrofit.Builder()
.baseUrl(BASE_URL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(ApiService::class.java)
}
}
2.3 使用API #
kotlin
class MainViewModel : ViewModel() {
private val apiService = RetrofitClient.apiService
private val _users = MutableLiveData<List<User>>()
val users: LiveData<List<User>> = _users
private val _error = MutableLiveData<String>()
val error: LiveData<String> = _error
fun loadUsers() {
viewModelScope.launch {
try {
val result = apiService.getUsers()
_users.value = result
} catch (e: Exception) {
_error.value = e.message
}
}
}
fun searchUsers(name: String) {
viewModelScope.launch {
try {
val result = apiService.searchUsers(name)
_users.value = result
} catch (e: Exception) {
_error.value = e.message
}
}
}
}
三、请求注解 #
3.1 HTTP方法注解 #
| 注解 | 说明 |
|---|---|
| @GET | GET请求 |
| @POST | POST请求 |
| @PUT | PUT请求 |
| @DELETE | DELETE请求 |
| @PATCH | PATCH请求 |
| @HEAD | HEAD请求 |
| @HTTP | 自定义方法 |
3.2 参数注解 #
| 注解 | 说明 | 示例 |
|---|---|---|
| @Path | 路径参数 | @Path(“id”) id: Int |
| @Query | 查询参数 | @Query(“name”) name: String |
| @QueryMap | 查询参数Map | @QueryMap params: Map<String, String> |
| @Body | 请求体 | @Body user: User |
| @Field | 表单字段 | @Field(“name”) name: String |
| @FieldMap | 表单字段Map | @FieldMap fields: Map<String, String> |
| @Header | 请求头 | @Header(“Authorization”) token: String |
| @HeaderMap | 请求头Map | @HeaderMap headers: Map<String, String> |
3.3 示例 #
kotlin
interface ApiService {
// 路径参数
@GET("users/{id}/posts/{postId}")
suspend fun getPost(@Path("id") userId: Int, @Path("postId") postId: Int): Post
// 查询参数
@GET("users")
suspend fun getUsers(
@Query("page") page: Int,
@Query("size") size: Int,
@Query("sort") sort: String? = null
): List<User>
// 查询参数Map
@GET("users")
suspend fun searchUsers(@QueryMap params: Map<String, String>): List<User>
// 请求体
@POST("users")
suspend fun createUser(@Body user: User): User
// 表单提交
@FormUrlEncoded
@POST("login")
suspend fun login(
@Field("username") username: String,
@Field("password") password: String
): LoginResponse
// 请求头
@GET("users")
suspend fun getUsers(
@Header("Authorization") token: String,
@Header("Accept-Language") language: String
): List<User>
// 动态URL
@GET
suspend fun getFromUrl(@Url url: String): ResponseBody
}
四、响应处理 #
4.1 Response包装 #
kotlin
@GET("users/{id}")
suspend fun getUser(@Path("id") id: Int): Response<User>
// 使用
val response = apiService.getUser(1)
if (response.isSuccessful) {
val user = response.body()
} else {
val errorBody = response.errorBody()?.string()
}
4.2 自定义响应类 #
kotlin
data class ApiResponse<T>(
val code: Int,
val message: String,
val data: T?
)
@GET("users")
suspend fun getUsers(): ApiResponse<List<User>>
五、拦截器 #
5.1 认证拦截器 #
kotlin
class AuthInterceptor(private val tokenProvider: () -> String?) : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request().newBuilder()
tokenProvider()?.let { token ->
request.addHeader("Authorization", "Bearer $token")
}
return chain.proceed(request.build())
}
}
// 使用
val okHttpClient = OkHttpClient.Builder()
.addInterceptor(AuthInterceptor { tokenManager.getToken() })
.build()
5.2 错误处理拦截器 #
kotlin
class ErrorInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val response = chain.proceed(chain.request())
if (!response.isSuccessful) {
when (response.code) {
401 -> throw UnauthorizedException()
403 -> throw ForbiddenException()
404 -> throw NotFoundException()
500 -> throw ServerException()
}
}
return response
}
}
六、数据转换器 #
6.1 Gson转换器 #
kotlin
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
val retrofit = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.build()
6.2 Moshi转换器 #
kotlin
implementation("com.squareup.retrofit2:converter-moshi:2.9.0")
val retrofit = Retrofit.Builder()
.addConverterFactory(MoshiConverterFactory.create())
.build()
6.3 自定义转换器 #
kotlin
class StringConverterFactory : Converter.Factory() {
override fun responseBodyConverter(
type: Type,
annotations: Array<out Annotation>,
retrofit: Retrofit
): Converter<ResponseBody, *>? {
if (type == String::class.java) {
return Converter<ResponseBody, String> { body -> body.string() }
}
return null
}
}
七、文件上传下载 #
7.1 文件上传 #
kotlin
interface ApiService {
@Multipart
@POST("upload")
suspend fun uploadFile(
@Part file: MultipartBody.Part,
@Part("description") description: RequestBody
): UploadResponse
}
// 使用
val file = File("/path/to/file.jpg")
val requestFile = file.asRequestBody("image/jpeg".toMediaType())
val body = MultipartBody.Part.createFormData("file", file.name, requestFile)
val description = "Upload".toRequestBody("text/plain".toMediaType())
val response = apiService.uploadFile(body, description)
7.2 文件下载 #
kotlin
interface ApiService {
@Streaming
@GET("download/{filename}")
suspend fun downloadFile(@Path("filename") filename: String): ResponseBody
}
// 使用
suspend fun downloadFile(filename: String, destFile: File) {
val body = apiService.downloadFile(filename)
body.byteStream().use { input ->
destFile.outputStream().use { output ->
input.copyTo(output)
}
}
}
// 带进度下载
suspend fun downloadWithProgress(
filename: String,
destFile: File,
onProgress: (progress: Int) -> Unit
) {
val body = apiService.downloadFile(filename)
val contentLength = body.contentLength()
var downloaded = 0L
body.byteStream().use { input ->
destFile.outputStream().use { output ->
val buffer = ByteArray(4096)
var read: Int
while (input.read(buffer).also { read = it } != -1) {
output.write(buffer, 0, read)
downloaded += read
if (contentLength > 0) {
val progress = (downloaded * 100 / contentLength).toInt()
onProgress(progress)
}
}
}
}
}
八、封装网络层 #
8.1 Repository封装 #
kotlin
class UserRepository(private val apiService: ApiService) {
suspend fun getUsers(): Result<List<User>> {
return try {
val users = apiService.getUsers()
Result.success(users)
} catch (e: Exception) {
Result.failure(e)
}
}
suspend fun getUserById(id: Int): Result<User> {
return try {
val user = apiService.getUserById(id)
Result.success(user)
} catch (e: Exception) {
Result.failure(e)
}
}
suspend fun createUser(user: User): Result<User> {
return try {
val createdUser = apiService.createUser(user)
Result.success(createdUser)
} catch (e: Exception) {
Result.failure(e)
}
}
}
8.2 依赖注入 #
kotlin
// 使用Hilt
@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
@Provides
@Singleton
fun provideOkHttpClient(): OkHttpClient {
return OkHttpClient.Builder()
.addInterceptor(HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
})
.connectTimeout(30, TimeUnit.SECONDS)
.build()
}
@Provides
@Singleton
fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder()
.baseUrl("https://api.example.com/")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()
}
@Provides
@Singleton
fun provideApiService(retrofit: Retrofit): ApiService {
return retrofit.create(ApiService::class.java)
}
}
九、最佳实践 #
9.1 错误处理 #
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>()
data class Exception(val e: Throwable) : NetworkResult<Nothing>()
}
suspend fun <T> safeApiCall(apiCall: suspend () -> T): NetworkResult<T> {
return try {
NetworkResult.Success(apiCall())
} catch (e: HttpException) {
NetworkResult.Error(e.code(), e.message())
} catch (e: IOException) {
NetworkResult.Exception(e)
} catch (e: Exception) {
NetworkResult.Exception(e)
}
}
9.2 网络状态处理 #
kotlin
class NetworkAwareRepository(
private val apiService: ApiService,
private val context: Context
) {
suspend fun <T> safeNetworkCall(apiCall: suspend () -> T): NetworkResult<T> {
if (!isNetworkAvailable(context)) {
return NetworkResult.Error(-1, "No network connection")
}
return safeApiCall(apiCall)
}
}
十、总结 #
本章详细介绍了Retrofit:
- Retrofit的基本使用
- 请求注解的使用
- 响应处理
- 拦截器配置
- 数据转换器
- 文件上传下载
- 网络层封装
- 最佳实践
Retrofit是Android网络请求的最佳实践,配合OkHttp和协程可以高效地处理网络请求。
最后更新:2026-03-26