OkHttp完全解析(六)攔截器
攔截器是一種能夠監控,重寫,重試呼叫的強大機制。
呼叫chain.proceed(request)是每個攔截器實現的關鍵部分。這個看似簡單的方法是所有HTTP 工作發生的地方, 在這裡產生一個響應應答請求。
攔截器可以是鏈式的,假設你有一個壓縮攔截器和一個校驗攔截器,那麼需要決定資料是否被壓縮後進行校驗,或者是先校驗後壓縮。OkHttp採用列表的形式追蹤攔截器,攔截器會被有序呼叫。
7.1 應用攔截器
攔截器被註冊成為應用攔截器或者網路攔截器。下面通過上述定義的LoggingInterceptor來展示他們之間的不同。註冊一個應用攔截器通過呼叫OkHttpClient.interceptors()返回的List的add()方法完成。
URL http://www.publicobject.com/helloworld.txt
重定向到
https://publicobject.com/helloworld.txt, OkHttp自動追蹤這個重定向過程。我們的應用攔截器會被呼叫一次,從chain.proceed()返回的響應是重定向後的響應。
可以看到,請求被重定向了,因為response.request().url()返回的結果跟request.url()返回的結果不一致。兩條日誌列印了不一樣的URL。
7.2 網路攔截器
註冊網路攔截器和註冊應用攔截器很類似。只是通過networkInterceptors()方法取代了interceptore()方法。
可以看到,請求被重定向了,因為response.request().url()返回的結果跟request.url()返回的結果不一致。兩條日誌列印了不一樣的URL。
7.2 網路攔截器
註冊網路攔截器和註冊應用攔截器很類似。只是通過networkInterceptors()方法取代了interceptore()方法。
執行這段程式碼時,程式碼運行了兩次,一次是初始化請求,一次是重定向請求。
網路請求也包含更多資料,比如OkHttp頭部中添加了Accept-Encoding:gzip請求頭通知響應壓縮。網路攔截器的Chain中有一個非空的連線可以用於詢問連線到web伺服器時使用的IP地址和TLS配置。
7.3 在應用攔截器和網路攔截器之間如何選擇
每個攔截器各有自己的優點
應用攔截器
*不必要擔心響應和重定向之間的中間響應。
*通常只調用一次,即使HTTP響應是通過快取提供的。
*遵從應用層的最初目的。與OkHttp的注入頭部無關,如If-None-Match。
*允許短路而且不呼叫Chain.proceed()。
*允許重試和多次呼叫Chain.proceed()。
網路攔截器
*允許像重定向和重試一樣操作中間響應。
*網路發生短路時不呼叫快取響應。
*在資料被傳遞到網路時觀察資料。
*有權獲得裝載請求的連線。
7.4 重寫請求
通過攔截器可以新增,移除,替換請求頭。也可以改變請求的請求體。例如,在知道連線的web伺服器是否支援壓縮格式的情況下,可以使用應用攔截器新增請求體壓縮型別。
7.5 重寫響應
相對應地,攔截器可以重寫響應頭和改變響應體。這一點比重寫寫請求頭要危險,因為可能違反web伺服器的期望。
如果你處於一種比較糾結的狀態,並且準備處理結果,那麼重寫響應頭是解決問題的有效方法。例如,可以修復伺服器配置錯誤的Cache-Control響應頭是快取更高效。
典型情況,這樣做比在伺服器上處理這個問題要方便得多。
7.6 實用性
OkHttp攔截器在OkHttp2.2以後更優。不過,沒有OkUrlFactory,攔截器無法工作,基於OkHttp構建的框架有Retrofit<=1.8 版本和Picasso<=2.4版本。
7.5 重寫響應
相對應地,攔截器可以重寫響應頭和改變響應體。這一點比重寫寫請求頭要危險,因為可能違反web伺服器的期望。
如果你處於一種比較糾結的狀態,並且準備處理結果,那麼重寫響應頭是解決問題的有效方法。例如,可以修復伺服器配置錯誤的Cache-Control響應頭是快取更高效。
典型情況,這樣做比在伺服器上處理這個問題要方便得多。
7.6 實用性
OkHttp攔截器在OkHttp2.2以後更優。不過,沒有OkUrlFactory,攔截器無法工作,基於OkHttp構建的框架有Retrofit<=1.8 版本和Picasso<=2.4版本。