OkHttp 與 Retrofit 完美結合:打造高效的 Android 網絡請求

前言

在現代 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()

四、最佳實踐

  1. 單例模式:Retrofit 和 OkHttpClient 的創建成本較高,應該使用單例模式

  2. 合理配置超時時間:根據應用需求設置連接、讀取和寫入超時

  3. 日志攔截器:在 debug 版本中添加日志攔截器方便調試

  4. 錯誤處理:統一處理網絡錯誤和業務錯誤

  5. 進度監聽:對于大文件上傳下載,實現進度監聽

  6. 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 應用的網絡請求效率和代碼質量。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/89922.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/89922.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/89922.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

系統辨識建模

系統辨識建模 一、系統辨識建模的作用 1. 建立真實物理系統的數學模型 2. 為后續控制器/強化學習算法提供仿真環境 3. 提高控制精度和安全性 二、本文的系統辨識是怎么做的 1. 實驗采集 2. 數學建模 3. 在控制系統中的作用 三、實際用法流程(簡化版) 1. 系統辨識階段 2. 強化…

Android開發:Java與Kotlin深度對比

1. 語言特性與現代性 Java (特別是 Android 主要使用的 Java 8 及之前版本): 相對冗長&#xff1a; 需要編寫更多的樣板代碼&#xff08;如 getter/setter、findViewById 的顯式類型轉換、匿名內部類等&#xff09;。空指針異常 (NPE)&#xff1a; 類型系統默認允許 null&#…

米家打印機驅動:Wi-Fi 無線打印絲滑順暢不卡頓,從此告別對打印機干瞪眼

各位小米家居控們&#xff0c;你們有沒有過這種經歷&#xff0c;新買的打印機回家&#xff0c;結果電腦跟它像倆傲嬌的小情侶&#xff0c;死活不搭話&#xff1f;急得你想當場表演一個“打印機抱頭痛哭”&#xff1f;別急&#xff0c;今天就給你們安利個神隊友——米家打印機驅…

日語學習-日語知識點小記-構建基礎-JLPT-N3階段(7):自動詞 & 他動詞

日語學習-日語知識點小記-構建基礎-JLPT-N3階段&#xff08;7&#xff09;&#xff1a;自動詞 &#xff06; 他動詞1、前言&#xff08;1&#xff09;情況說明&#xff08;2&#xff09;工程師的信仰2、知識點&#xff08;&#xff11;&#xff09;自動詞 &#xff06; 他動…

深入理解設計模式:訪問者模式詳解

在軟件開發中&#xff0c;我們經常會遇到需要對一個復雜對象結構進行操作的情況。隨著需求的不斷變化&#xff0c;我們可能需要在這個對象結構上添加各種新的操作。如果直接在對象結構中添加這些操作&#xff0c;會導致類的職責過重&#xff0c;且每次添加新操作都需要修改原有…

Linux timerfd 定時器封裝

使用 timerfd epoll() 實現&#xff0c;簡潔精確。沒定義 MU_ERROR 宏的話替換為 printf 即可。mu_timer.h:#ifndef _MU_TIMER_H_ #define _MU_TIMER_H_#ifdef __cplusplus extern "C" { #endif#include <stdint.h> #include <time.h> #include <pth…

【樣式效果】Vue3實現仿制iOS按鈕動態效果

iOS開關效果定義變量&#xff1a; <style scoped lang"scss">.layout {// 按鈕寬度$button-width: 500px;// 按鈕高度$button-height: 250px;// 按鈕里面圓形直徑$circle-diameter: 200px;// 按鈕背景與里面圓形間距$button-circle-offset:calc(($button-he…

京東瘋狂投資具身智能:眾擎機器人+千尋智能+逐際動力 | AI早報

每日分享全球最新AI資訊【應用商業八卦技術】&#xff0c;&#x1f30f;&#xff1a;未來世界2099應用 1、馬斯克推出兒童AI"Baby Grok"引熱議&#xff1a;安全性能否經受考驗&#xff1f; 2、螞蟻AQ健康應用霸榜蘋果商店&#xff0c;或將聯手Apple Watch打造智能健康…

Jiasou TideFlow AIGC SEO Agent:全自動外鏈構建技術重構智能營銷新標準

AI時代SEO技術革命&#xff1a;企業如何突破流量增長瓶頸&#xff1f;隨著Google算法升級至MUM模型&#xff0c;傳統SEO工具已難以應對多模態內容優化需求。在搜索引擎日均處理120億次查詢的生態中&#xff0c;企業官網平均自然流量轉化周期長達6-8個月&#xff0c;因此諸如Jia…

Docker-compose:服務編排

Docker-compose 介紹 服務編排:按照一定的業務規則批量管理容器 在微服務架構的應用系統中,一般包含 N 個微服務,且每個微服務一般都會部署多個實例。此時,如果每個微服務都要手動啟停,維護的工作量會很大。 要從 Dockerfile build image 或者去 docker hub 拉取 image …

異地服務器備份Mysql數據

前言異地服務器備份Mysql數據即Mysql的server端與備份服務器不是同一個。Mysql服務端安裝在192.168.3.36中&#xff0c;現在需要在IP為192.168.209.129的服務器中使用mysqldump命令備份指定數據庫數據;192.168.209.129沒有裝過Mysql客戶端;1.安裝Mysql客戶端不安裝Mysql客戶端就…

NGINX 高級配置解析:`proxy_request_buffering` 使用詳解

在使用 NGINX 作為反向代理服務器時&#xff0c;處理客戶端請求體&#xff08;如上傳文件或大體積 POST 請求&#xff09;的方式會直接影響應用性能與資源使用。其中&#xff0c;proxy_request_buffering 是一個非常關鍵但容易被忽略的配置項。 本文將詳細介紹該指令的作用、典…

增加交叉驗證和超參數調優

前文中&#xff0c;只是給了基礎模型&#xff1a; PyTorch 實現 CIFAR-10 圖像分類&#xff1a;從數據預處理到模型訓練與評估-CSDN博客 今天我們增加交叉驗證和超參數調優&#xff0c; 先看運行結果&#xff1a; 在測試集上評估最終模型 最終模型在測試集上的準確率&…

解決pip指令超時問題

用pip指令&#xff0c;在安裝Django3.2時報錯&#xff0c;詢問ChatGpt后得到的解決方案pip 下載超時 —— 是 當前網絡連接到 PyPI 官方源太慢或不穩定&#xff0c;甚至可能連不上了&#xff0c;而 pip 默認的超時時間又太短&#xff0c;就導致了中途失敗&#xff1a;ReadTimeo…

Oracle定時清理歸檔日志

線上歸檔日志滿了&#xff0c;系統直接崩了&#xff0c;為解決這個問題&#xff0c;創建每月定時清理歸檔日志。 創建文件名 delete_archivelog.rman CONFIGURE ARCHIVELOG DELETION POLICY CLEAR; RUN {ALLOCATE CHANNEL c1 TYPE DISK;DELETE ARCHIVELOG ALL COMPLETED BEFORE…

ELF 文件操作手冊

目錄 一、ELF 文件結構概述 二、查看 ELF 文件頭信息 1、命令選項 2、示例輸出 3、內核數據結構 三、ELF 程序頭表 1、命令選項 2、示例輸出 3、關鍵說明 4、內核數據結構 四、ELF 節頭表詳解 查看節頭表信息 1、命令選項 2、示例輸出 3、標志說明 4、重要節說…

深入淺出Python函數:參數傳遞、作用域與案例詳解

&#x1f64b;?♀? 博主介紹&#xff1a;顏顏yan_ ? 本期精彩&#xff1a;深入淺出Python函數&#xff1a;參數傳遞、作用域與案例詳解 &#x1f3c6; 熱門專欄&#xff1a;零基礎玩轉Python爬蟲&#xff1a;手把手教你成為數據獵人 &#x1f680; 專欄亮點&#xff1a;零基…

ps aux 和 ps -ef

在 Linux/Unix 系統中&#xff0c;ps aux 和 ps -ef 都是用于查看進程信息的命令&#xff0c;結合 grep node 可以篩選出與 Node.js 相關的進程。它們的核心功能相似&#xff0c;但在輸出格式和選項含義上有區別&#xff1a;1. 命令對比命令含義主要區別ps auxBSD 風格語法列更…

Spark ML 之 LSH

src/test/scala/org/apache/spark/ml/feature/BucketedRandomProjectionLSHSuite.scala test("approxSimilarityJoin for self join") {val data = {for (i <- 0 until 24) yield Vectors

關鍵成功因素法(CSF)深度解析:從戰略目標到數據字典

關鍵成功因素法由John Rockart提出&#xff0c;用于信息系統規劃&#xff0c;幫助企業識別影響系統成功的關鍵因素&#xff0c;從而確定信息需求&#xff0c;指導信息技術管理。該方法通過識別關鍵成功因素&#xff0c;找出關鍵信息集合&#xff0c;確定系統開發優先級&#xf…