簡介:大三學生黨一枚!主攻Android開發,對於Web和後端均有了解。
個人語錄:取乎其上,得乎其中,取乎其中,得乎其下,以頂級態度寫好一篇的博客。
上一篇給男朋友介紹了Okhttp
的基礎知識,OkHttpClient
,Request
,Call
,RealCall
以及同步執行和異步執行的源碼解釋。從這篇博客開始,會給男朋友深入分析攔截器鏈!攔截器鏈是OkHttp
的一個核心內容,非常非常重要,問到OkHttp
不可能不問攔截器鏈!我們先簡介一下攔截器的思想,然後再對每一個攔截器做詳細的介紹!
攔截器
一.攔截器的分類
這裏僅介紹系統提供的幾種攔截器,其實在官方的介紹中,攔截器的流程如圖:
攔截器的流程:當一個請求被執行時,系統會執行 Application Intercepter
,可以理解爲用戶自定義的攔截器,然後執行Okhttp的核心攔截器鏈,經過一系列攔截器的加工和判斷最終纔會進行網絡請求!
下面先簡單介紹每一種攔截器的功能,後面會開闢專門的章節講解每一個攔截器的源碼!
1.1 retryAndFollowUpInterceptor
重試和重定向攔截器:該攔截器是攔截器鏈的第一個,它的作用就和它的名稱一樣,當我們訪問某個服務出現某種異常時,比如該網站需要身份驗證,又或者需要進行重定向,這些異常最後會返回到重定向攔截器這裏被攔截,他可以對原始請求進行一些操作後自動進行重連嘗試。列舉幾種情況:
- 需要驗證:爲原始的
Request
添加身份驗證信息後,自動重新連接 - 重定向:原有網站不能提供服務,需要跳轉到新的一個端口或者服務,那麼將原始請求的
URL
更改爲重定向指向的URL
,自動重新連接。
Question:是不是所有失敗的情況都會重新連接?
並不是,只對某些異常做重新連接的嘗試!它的優點在於,對於某些不嚴重的異常或者並不是錯誤引起的請求錯誤自動進行重試!!!
1.2 BridgeInterceptor
關於BridgeInterceptor的作用,官方的描述是這樣的
Bridges from application code to network code.
First it builds a network request from a user
request. Then it proceeds to call the network.
Finally it builds a user response from the network response.
英文好的盆友肯定理解了,BridgeInterceptor
攔截器的作用就是把用戶的Resquest
轉換成符合網絡規範的Request
,當服務器返回Response
時,又將複合網絡規範的Response
轉換成用戶的Response
,這樣的好處是什麼?我們使用起來更方便了,不需要自己去定義請求頭的一些格式,也無需要關心返回Response
的解壓,把精力投放在業務需要上即可!
1.3 CacheInterceptor
緩存攔截器的作用,官方解釋
Serves requests from the cache and writes responses to the cache
簡而言之,如果該請求之前已經執行過,並且Response被緩存了,如果經過判斷,該緩存可用,就不需要再繼續下面的攔截器請求了,直接返回該Response,節省了網絡請求的時間,加快速度。能夠被緩存的請求的請求方法一定是GET
,其他的請求方法都不會被緩存。CacheInterceptor的作用其很簡單,但是內部的源碼比較複雜,都會開闢專門章節進行講解!
1.4 ConnectInterceptor
官方描述的作用
Opens a connection to the target server and proceeds to the next interceptor.
就是開啓一個和目標服務器的連接,然後就執行後面的CallServerInterceptor
攔截器了,其實更像是爲後面的攔截器做鋪墊,創建好一條Connection
!當然它的連接是如何創建的呢?後面會有介紹。
1.5 CallServerInterceptor
This is the last interceptor in the chain. It makes a network call to the server.
他是最後一個攔截器,它的作用就是通過創建好的鏈接,將Request
寫入網絡的IO流中,並從IO流中讀取返回的Response
。
二.攔截器的原理
上面簡單的介紹了幾種攔截器的作用,但是Okhttp
是怎麼實現攔截器鏈的呢?鏈是怎麼形成的呢?還是得回到源代碼中尋找答案!
首先看看RealCall
中的getResponseWithInterceptorChain()
方法
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
//構建了一個攔截器的鏈表,並將默認的五種攔截器添加進列表
List<Interceptor> interceptors = new ArrayList<>();
interceptors.addAll(client.interceptors());
interceptors.add(retryAndFollowUpInterceptor);
interceptors.add(new BridgeInterceptor(client.cookieJar()));
interceptors.add(new CacheInterceptor(client.internalCache()));
interceptors.add(new ConnectInterceptor(client));
if (!forWebSocket) {
interceptors.addAll(client.networkInterceptors());
}
interceptors.add(new CallServerInterceptor(forWebSocket));
//通過鏈表構建攔截器鏈Interceptro.Chain
Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
originalRequest, this, eventListener, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
//最後調用了攔截器鏈的proceed()方法
return chain.proceed(originalRequest);
}
再來看看preceed()方法做了什麼吧!
// Call the next interceptor in the chain.這裏重新構建了一個攔截器鏈,但是index+1。
RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
writeTimeout);
Interceptor interceptor = interceptors.get(index);//index==0,所以取出第一個
Response response = interceptor.intercept(next);//執行第一個攔截器。然後以後繼續執行下一個攔截器得到Response,只有執行到最後一個攔截器纔會得到Response,返回給最初的調用者。這也就是攔截器鏈的實現原理
三.總結
本篇簡單的介紹了幾種攔截器的作用,並介紹了攔截器的原理。後面我們會詳細介紹每一種攔截器的源代碼!!!男朋友聽完都說好!!!
先別走,我有一個資源學習羣要推薦給你,它是白嫖黨的樂園,小白的天堂!
別再猶豫,一起來學習!