前言
在现代 Android 开发中,网络请求是几乎每个应用都必不可少的功能。OkHttp 和 Retrofit 作为当前最流行的网络请求库组合,为开发者提供了简洁高效的解决方案。本文将详细介绍如何将这两者结合使用,充分发挥它们的优势。
一、OkHttp 和 Retrofit 简介
1. OkHttp
OkHttp 是一个高效的 HTTP 客户端,具有以下特点:
支持 HTTP/2,允许所有请求共享同一个 socket
连接池减少请求延迟
透明的 GZIP 压缩
响应缓存避免重复网络请求
自动处理网络问题,支持请求重试
2. Retrofit
Retrofit 是一个基于 OkHttp 的 RESTful HTTP 网络请求框架,它:
通过接口和注解配置网络请求
支持多种数据解析方式(Gson、Jackson、Moshi 等)
支持 RxJava 和 Coroutines
将 HTTP API 转换为 Java/Kotlin 接口
二、基本集成与使用
1. 添加依赖
首先在 build.gradle 中添加依赖:
implementation 'com.squareup.okhttp3:okhttp:4.9.3'
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0' // Gson 转换器
2. 创建 Retrofit 实例
val okHttpClient = OkHttpClient.Builder().connectTimeout(30, TimeUnit.SECONDS).readTimeout(30, TimeUnit.SECONDS).writeTimeout(30, TimeUnit.SECONDS).build()val retrofit = Retrofit.Builder().baseUrl("https://api.example.com/").client(okHttpClient).addConverterFactory(GsonConverterFactory.create()).build()
3. 定义 API 接口
interface ApiService {@GET("users/{id}")suspend fun getUser(@Path("id") userId: String): User@POST("users")suspend fun createUser(@Body user: User): Response<Unit>@GET("users")suspend fun getUsers(@Query("page") page: Int): List<User>
}
4. 发起网络请求
val apiService = retrofit.create(ApiService::class.java)// 使用协程
lifecycleScope.launch {try {val user = apiService.getUser("123")// 处理 user 数据} catch (e: Exception) {// 处理异常}
}
三、高级功能与配置
1. 添加公共请求头和参数
通过 OkHttp 的拦截器实现:
val okHttpClient = OkHttpClient.Builder().addInterceptor { chain ->val originalRequest = chain.request()val requestWithHeaders = originalRequest.newBuilder().header("Authorization", "Bearer token").header("Accept", "application/json").method(originalRequest.method, originalRequest.body).build()chain.proceed(requestWithHeaders)}.addInterceptor(HttpLoggingInterceptor().apply {level = HttpLoggingInterceptor.Level.BODY}).build()
2. 缓存配置
val cacheSize = 10 * 1024 * 1024 // 10 MB
val cache = Cache(File(context.cacheDir, "httpCache"), cacheSize.toLong())val okHttpClient = OkHttpClient.Builder().cache(cache).addInterceptor { chain ->val request = chain.request()val response = chain.proceed(request)val cacheControl = CacheControl.Builder().maxAge(1, TimeUnit.HOURS).build()response.newBuilder().header("Cache-Control", cacheControl.toString()).build()}.build()
3. 文件上传与下载
文件上传:
@Multipart
@POST("upload")
suspend fun uploadFile(@Part file: MultipartBody.Part,@Part("description") description: RequestBody
): Response<UploadResponse>// 使用示例
val file = File(filePath)
val requestFile = RequestBody.create("image/*".toMediaTypeOrNull(), file)
val part = MultipartBody.Part.createFormData("file", file.name, requestFile)
val description = "This is a test file".toRequestBody()apiService.uploadFile(part, description)
文件下载:
@Streaming
@GET
suspend fun downloadFile(@Url fileUrl: String): Response<ResponseBody>// 使用示例
val response = apiService.downloadFile("https://example.com/file.zip")
if (response.isSuccessful) {val inputStream = response.body()?.byteStream()// 保存文件
}
4. 错误统一处理
val okHttpClient = OkHttpClient.Builder().addInterceptor { chain ->val request = chain.request()val response = chain.proceed(request)when (response.code) {401 -> {// 处理未授权throw UnauthorizedException()}404 -> {// 处理未找到throw NotFoundException()}in 500..599 -> {// 处理服务器错误throw ServerException()}else -> response}}.build()
四、最佳实践
单例模式:Retrofit 和 OkHttpClient 的创建成本较高,应该使用单例模式
合理配置超时时间:根据应用需求设置连接、读取和写入超时
日志拦截器:在 debug 版本中添加日志拦截器方便调试
错误处理:统一处理网络错误和业务错误
进度监听:对于大文件上传下载,实现进度监听
HTTPS 安全配置:正确配置 HTTPS 证书验证
五、完整示例代码
object RetrofitClient {private const val BASE_URL = "https://api.example.com/"private val okHttpClient by lazy {OkHttpClient.Builder().connectTimeout(30, TimeUnit.SECONDS).readTimeout(30, TimeUnit.SECONDS).writeTimeout(30, TimeUnit.SECONDS).addInterceptor(HttpLoggingInterceptor().apply {level = if (BuildConfig.DEBUG) {HttpLoggingInterceptor.Level.BODY} else {HttpLoggingInterceptor.Level.NONE}}).addInterceptor { chain ->val originalRequest = chain.request()val request = originalRequest.newBuilder().header("Authorization", "Bearer ${getToken()}").header("Accept", "application/json").method(originalRequest.method, originalRequest.body).build()chain.proceed(request)}.build()}private val retrofit by lazy {Retrofit.Builder().baseUrl(BASE_URL).client(okHttpClient).addConverterFactory(GsonConverterFactory.create()).build()}val apiService: ApiService by lazy {retrofit.create(ApiService::class.java)}private fun getToken(): String {// 从 SharedPreferences 或其他地方获取 tokenreturn ""}
}// 使用示例
lifecycleScope.launch {try {val users = RetrofitClient.apiService.getUsers(page = 1)// 更新 UI} catch (e: Exception) {// 处理错误}
}
六、总结
OkHttp 和 Retrofit 的结合为 Android 网络请求提供了强大而灵活的解决方案。OkHttp 负责底层的网络通信,而 Retrofit 则提供了更高层次的抽象,使网络请求的代码更加简洁和易于维护。通过合理配置和扩展,可以满足各种复杂的网络请求需求。
在实际项目中,我们可以根据具体需求进一步扩展,例如添加请求重试机制、自定义数据解析器、集成 RxJava 或 Coroutines 等。掌握这两者的结合使用,将大大提高 Android 应用的网络请求效率和代码质量。