okhttp3全面解析及源碼分析(一:宏觀介紹及基礎用法)

一、簡介

1.1 okhttp是什麼?

   okhttp是由美國square [square是什麼] 公司開發的,用於安卓和java應用程序的 HTTP+HTTP/2的客戶端。

1.2 最新的版本

   目前最新版本爲 okhttp3,可以從這個鏈接獲取最新版本的okhttp3的版本號及maven構件地址: https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp
   gradle最新版本: compile group: ‘com.squareup.okhttp3’, name: ‘okhttp’, version: ‘4.7.2’

   這裏需要注意的是okhttp從大的版本上來說分爲兩個版本,即okhttp和okhttp3。okhttp可以認是第一個大版本,但從2016年開始就不再維護了;可能有人會有疑問爲什麼沒有okhttp2這個大版本,我猜可能是因爲內部團隊存在多個優化版本,導致無法統一,因此沒有對外發布okhttp2,直接進入了okhttp3。
   在mvnreponsitory倉庫中okhttp3的第一個版本爲2016年1月發佈的3.0.0版本,一直由square維護至今,到本博客的撰寫時間,okhttp3的最新版本爲 4.7.2版本,發佈日期爲2020年5月。

1.3 okhttp的優點

   1.3.1 官方宣傳的優點

   官方自稱的優點[okhttp的github官方宣傳] ,翻譯過來的意思大概是說:

   okhttp是現代化應用程序的網絡通信的方式。它用來幫助程序交換數據和媒體信息,使用okhttp可以讓你的程序加載物料(翻譯爲服務器數據更合適在)更加高效、更節省網絡帶寬。

   okhttp通過以下措施讓你的網絡更加高效
1. HTTP/2支持對同一個host的所有網絡請求 共享socket。
2. 在不啓用HTTP/2的情況,連接池能減少潛在的網絡請求。
3. 透明GZIP技術壓縮了下載數據的大小。
4. 結果緩存技術避免重複的網絡請求。

   OkHttp在網絡出現問題時,仍然能支持良好的運行。它能解決常見的網絡連接問題。如果你的服務端有多個ip地址,okhttp會在第一個地址連接失敗時,自動嘗試備用地址。 這種技術在你的服務器有多地備份時,是必須要用到的。OkHttp支持現代TLS特性(TLS 1.3、ALPN、證書固定)。可以將其配置爲回滾以實現廣播連接。

1.3.2 用戶總結的優點-(版本一)
  • 支持HTTP2/SPDY(SPDY是Google開發的基於TCP的傳輸層協議,用以最小化網絡延遲,提升網絡速度,優化用戶的網絡使用體驗。)
  • socket自動選擇最好路線,並支持自動重連,擁有自動維護的socket連接池,減少握手次數,減少了請求延遲,共享Socket,減少對服務器的請求次數。
  • 基於Headers的緩存策略減少重複的網絡請求。
  • 擁有Interceptors輕鬆處理請求與響應(自動處理GZip壓縮)。
1.3.3 用戶總結的優點-(版本二)
  • 支持HTTP2/SPDY(SPDY是Google開發的基於TCP的傳輸層協議,用以最小化網絡延遲,提升網絡速度,優化用戶的網絡使用體驗。)
  • socket自動選擇最好路線,並支持自動重連,擁有自動維護的socket連接池,減少握手次數,減少了請求延遲,共享Socket,減少對服務器的請求次數。
  • 基於Headers的緩存策略減少重複的網絡請求。
  • 擁有Interceptors輕鬆處理請求與響應(自動處理GZip壓縮)。

1.4 okhttp的應用

  1. 用於替代HttpUrlConnection和Apache HttpClient
  2. Android4.4開始,google已經開始將源碼中的HttpURLConnection替換爲OkHttp
  3. Android6.0裏已移除HttpClient

1.5 okhttp的依賴關係

從下圖可以看出:

  1. okhttp默認是依賴okio的。
  2. okhttp3: 4.7.2完全使用的是 kotlin編寫的
okhttp的依賴關係圖 okhttp3-4.7.2.jar包
在這裏插入圖片描123 在這裏插入圖片描述

二、基本使用

     應用okhttp時,主要會關注幾個方面的問題,請求的方法類型、同步異步、上傳文件、下載文件、上傳文件同時攜帶參數。

2.1 異步get請求

在這裏插入圖片描述

2.2 異步post請求

在這裏插入圖片描述

2.3 同步get請求

在這裏插入圖片描述

2.4 同步post請求

在這裏插入圖片描述

2.5 get下載文件

在這裏插入圖片描述

2.6 post上傳文件

上傳任何文件都需要設置文件類型的MIME,例如上傳一個純文本文件,就需要MediaType.parse(“text/plain; charset=utf-8”)

舉例說明 MIME值域
在這裏插入圖片描述 在這裏插入圖片描述

2.7 異步上傳Multipart文件,同時攜帶額外參數

  • 應用場景舉例:
       我們在有些情況下既要上傳文件還要上傳其他類型字段。比如在個人中心我們可以修改名字,年齡,修改圖像,這其實就是一個表單。這裏我們用到MuiltipartBody ,它 是RequestBody 的一個子類,我們提交表單就是利用這個類來構建一個 RequestBody。
    在這裏插入圖片描述

三、不常用的功能

3.1 設置超時和緩存

在這裏插入圖片描述

3.1.1 超時的解釋:
  • callTimeout = 0 : 請求超時時長,默認爲0,0表示不限制。

    1. Sets the default timeout for complete calls. A value of 0 means no timeout.
    2. The call timeout spans the entire call: resolving DNS, connecting, writing the request body,
      server processing, and reading the response body. If the call requires redirects or retries
      all must complete within one timeout period.
      解讀:callTimeout指整個請求生命週期的所有時間,包含dns解析、發起socket連接、寫入請求數據、等待服務器處理、讀取服務器返回的數據, 通常不需要設置。 這也解釋了爲什麼我們在項目設置的請求超時時間都是10秒,但實在開發過程中總會碰到超過10秒的情況。這是因爲對10秒的理解不夠深刻。
  • connectTimeout = 10_000

    1. Sets the default connect timeout for new connections. A value of 0 means no timeout,
    2. The connect timeout is applied when connecting a TCP socket to the target host. The default
      value is 10 seconds.
  • writeTimeout = 10_000

    1. Sets the default write timeout for new connections. A value of 0 means no timeout
    2. The write timeout is applied for individual write IO operations. The default value is 10 seconds.
  • readTimeout = 10_000

    1. Sets the default read timeout for new connections. A value of 0 means no timeout
    2. The read timeout is applied to both the TCP socket and for individual read IO operations including on [Source] of the [Response]. The default value is 10 seconds.

3.2 設置請求頭

在這裏插入圖片描述

3.3 取消請求

  • 場景:

  某些特殊的場景下需要取消網絡請求,比如下載文件時用戶點擊了暫停或取消按鈕、某Activity正在請求數據時用戶finish關閉掉了當前頁面,這些場景下就必須取消請求,以減小資源消耗(如內存、網絡、cpu等)。

  • 解決方法:

  OkHttp提供了cancel方法,但是實際在使用過程中發現,如果調用cancel()方法,會回調到CallBack裏面的 onFailure方法中。測試發現不同的失敗類型返回的IOException e 不一樣,所以可以通過e.toString 中的關鍵字來區分不同的錯誤類型。

自己主動取消的錯誤的 java.net.SocketException: Socket closed
超時的錯誤是 java.net.SocketTimeoutException
網絡出錯的錯誤是java.net.ConnectException: Failed to connect to xxxxx

  針對這個問題,可以封裝callback的onFailure方法,過濾掉主動取消的狀況,以免在不必要的場景下,彈出錯誤toast提示
在這裏插入圖片描述

  • 取消單個請求:

  可以通過 call.cancel(); 來取消單個網絡請求。
   okhttp源碼中對cancel()方法的說明:如果可能的話,將會取消請求。如果請求已經完成,那麼將不會被取消。 這意味着,未發出的請求、及正進行中的請求都將會被及時取消。 至少源碼是如何實現取消正在進行中的請求,後面源碼解讀時再具體分析。
在這裏插入圖片描述
取消請求的例子:
在這裏插入圖片描述

  • 取消全部請求:

    okhttpclient.dispatcher().cancelAll();

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章