前言
在現代 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 應用的網絡請求效率和代碼質量。