【Android】OKHttp網絡請求原理和弱網優化
1. OkHttp 網絡請求原理
OkHttp 的請求過程可以分為 四個關鍵階段:
(假設你是通過 OkHttpClient.newCall(request).enqueue(callback)
發的請求)
OkHttpClient│▼
Dispatcher (調度器)│▼
RealCall (真正的Call實現)│▼
Interceptor Chain (攔截器責任鏈)│▼
Stream/Connection (TCP/SSL/HTTP2)
核心組件
- OkHttpClient
- 全局配置(超時、攔截器、連接池、緩存等)
- 線程安全,推薦單例。
- Dispatcher(調度器)
- 維護同步/異步請求隊列
- 默認異步最大并發請求數 = 64(每個host默認5個并發)
- RealCall
- 封裝了一個具體的 HTTP 調用過程。
- 同步時走
execute()
,異步時走enqueue()
。
- Interceptor Chain(攔截器鏈)
OkHttp 的核心,按順序執行:- Application Interceptor(應用攔截器)
你自己加的,比如統一加 Header、埋點。 - RetryAndFollowUpInterceptor(重試&重定向)
處理失敗重試、HTTP 3xx 跟隨跳轉。 - BridgeInterceptor(橋接攔截器)
把用戶的 Request 轉成可發的 HTTP Request(補默認 Header,比如 Content-Type)。 - CacheInterceptor(緩存攔截器)
負責讀寫緩存(符合 HTTP 緩存協議的才會生效)。 - ConnectInterceptor(連接攔截器)
找到可用的連接(可能復用連接池的 TCP/HTTP2)。 - CallServerInterceptor(發送請求 & 讀取響應)。
- Application Interceptor(應用攔截器)
- 連接池(ConnectionPool)
- 復用 TCP 連接(默認 5 分鐘閑置后關閉)
- 對弱網非常重要,減少 TCP/TLS 握手開銷。
2. 弱網優化思路(基于 OkHttp 原理)
弱網優化要考慮 連接建立、數據傳輸、失敗恢復 三方面:
(1) 減少連接開銷
-
啟用連接池(默認已開啟)
new OkHttpClient.Builder().connectionPool(new ConnectionPool(10, 5, TimeUnit.MINUTES))
提高空閑連接數和保活時間,減少頻繁建連。
-
HTTP/2
如果服務端支持,啟用 HTTP/2 可以一個 TCP 連接多路復用多個請求,減少弱網下握手阻塞。 -
DNS 預解析 + 緩存
弱網 DNS 解析可能很慢,可以提前解析:OkHttpClient client = new OkHttpClient.Builder().dns(hostname -> {List<InetAddress> addresses = Arrays.asList(InetAddress.getAllByName(hostname));return addresses; // 可做本地緩存}).build();
(2) 控制請求超時策略
弱網時默認超時可能不合適,可以分類型調整:
OkHttpClient client = new OkHttpClient.Builder().connectTimeout(5, TimeUnit.SECONDS) // 建立連接超時.readTimeout(8, TimeUnit.SECONDS) // 讀取超時.writeTimeout(8, TimeUnit.SECONDS) // 寫入超時.retryOnConnectionFailure(true) // 啟用失敗重試.build();
- 短連接超時:弱網時快速放棄連接不上的 IP,走備用。
- 讀寫時間略放寬:弱網傳輸慢,避免誤判失敗。
(3) 分片/斷點續傳
-
大文件上傳/下載弱網下易中斷,建議用 Range 分片:
Range: bytes=0-1023
-
中斷后只請求剩余部分,減少重傳。
(4) 降級策略
弱網下可以:
- 壓縮數據(Gzip / WebP 圖片)
OkHttp 默認支持 Gzip 解壓,服務端加Content-Encoding: gzip
即可。 - 減少請求次數
合并多個小請求為一個大請求。 - 先本地緩存/后上傳
弱網先本地存儲(Room/SQLite),網絡恢復后批量上傳。
(5) 智能重試
默認的 RetryAndFollowUpInterceptor
只會在特定錯誤下重試。
你可以自定義攔截器來做指數退避重試:
class RetryInterceptor implements Interceptor {@Overridepublic Response intercept(Chain chain) throws IOException {int tryCount = 0;IOException lastException;while (tryCount < 3) {try {return chain.proceed(chain.request());} catch (IOException e) {lastException = e;tryCount++;Thread.sleep((long) Math.pow(2, tryCount) * 500); // 500ms, 1s, 2s}}throw lastException;}
}
(6) 弱網檢測 + 動態策略
可用 TrafficStats
或測速接口判斷弱網,然后動態調整 OkHttp:
if (isWeakNetwork()) {// 降低并發、延長超時
} else {// 正常配置
}
? 總結
- OkHttp 的本質是攔截器責任鏈 + 連接池復用,弱網優化重點是減少握手、緩存結果、控制超時、重試與降級。
- 最實用的三個點:連接復用(ConnectionPool)、HTTP/2、重試退避策略。
- 如果弱網還卡,可以加弱網檢測配合動態參數調整。
還可以額外參考一下【淘寶移動端統一網絡庫的架構演進和弱網優化技術實踐】