OKHttp -- 結(jié)構(gòu)分析

OKHttp框架圖:


OkHttp源碼大概流程

這個(gè)圖片是從拆輪子系列:拆 OkHttp纪吮,大神對Okhttp源碼分析俩檬,他分析得特別好,推薦是看的博文碾盟。我只是結(jié)合他的總結(jié)棚辽,然后總結(jié)成自己的東西,寫一下冰肴,希望可以對okhttp更進(jìn)一步了解屈藐。
源碼有很多地方值得我們?nèi)W(xué)習(xí)。

一熙尉、Builder模式

OKHttpClient联逻,Request,Response等大量的使用這個(gè)模式检痰,這些類都需要大量的參數(shù)遣妥,所以使用Builder模式是很好的設(shè)計(jì)

  • 1、這個(gè)模式可以避免構(gòu)造方法需要傳入大量的參數(shù)攀细,相比使用setting的方式設(shè)置參數(shù)箫踩,使用Builder更加清晰。
  • 2谭贪、如果有大量的參數(shù)境钟,可能會(huì)有多個(gè)構(gòu)造方法,有一些默認(rèn)的參數(shù)俭识,這樣很容易使用了不對的構(gòu)造方法慨削。
  • 3、雖然增加了不少代碼量,但是客戶端的調(diào)用非常的清晰
    Builer模式的分析

二缚态、使用隊(duì)列管理請求磁椒,實(shí)現(xiàn)高并發(fā)

相應(yīng)的類RealCall、Dispatcher
Dispatcher內(nèi)部管理了三個(gè)隊(duì)列

三個(gè)隊(duì)列

同時(shí)Dispatcher設(shè)置了最大請求數(shù)64玫芦,設(shè)置了最大Host5
使用Dispatcher的finished方法控制隊(duì)列
將線程管理浆熔、線程池放在Dispatcher里面進(jìn)行管理,RealCall桥帆、AsyncCall負(fù)責(zé)執(zhí)行的邏輯医增。

同步excute的調(diào)用

異步調(diào)用A'syncCall最后的調(diào)用

不論是同步還是異步灌具,最后都是調(diào)用getResponseWithInterceptorChain()

三乞娄、責(zé)任鏈模式

OKHttp把責(zé)任鏈模式設(shè)計(jì)在最核心的地方鼠证,每一個(gè)請求會(huì)有連接疚膊、請求、處理返回等等一系列的任務(wù)锌蓄。在OKHttp中已攔截器作為每個(gè)責(zé)任的任務(wù)Interceptor

Interceptor

然后關(guān)聯(lián)到Chain的鏈條上熬尺,在Interceptor的每個(gè)intercept中褂始,在執(zhí)行Chain的proceed方法夺欲,知道Chain中沒有任務(wù)跪帝。
getResponseWithInterceptorChain

Interceptors

Interceptors

3.1 RetryAndFollowUpInterceptor

重試重定向攔截器,不斷判斷返回?cái)?shù)據(jù)洁闰,有問題重試或者重定向
會(huì)判斷后面攔截器返回的response的值,看是否請求完成万细,或者需要重定向或者重試
RetryAndFollowUpInterceptor的詳細(xì)分析

3.2 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.

將應(yīng)用代碼轉(zhuǎn)換成網(wǎng)絡(luò)代碼扑眉,對用戶發(fā)送請求的數(shù)據(jù)進(jìn)行校驗(yàn)并矯正;同時(shí)網(wǎng)絡(luò)請求返回的數(shù)據(jù)進(jìn)行處理赖钞,處理為用戶希望也是用戶能夠理解的數(shù)據(jù)腰素。
BridgeInterceptor源碼 主要看intercept方法
chain.proceed調(diào)用之前是對請求數(shù)據(jù)進(jìn)行轉(zhuǎn)換,調(diào)用之后是對請求返回?cái)?shù)據(jù)進(jìn)行轉(zhuǎn)換

3.3 CacheInterceptor 緩存攔截器

/** Serves requests from the cache and writes responses to the cache. */

讀取緩存和寫入更新緩存
緩存機(jī)制

3.4 ConnectInterceptor

ConnectInterceptor

看似簡單
StreamAllocation 分配流雪营,他實(shí)際上是在RetryAndFollowUpInterceptor中創(chuàng)建的弓千,那時(shí)候它負(fù)責(zé)把創(chuàng)建的對象傳給chain,如果需要重定向就會(huì)重新創(chuàng)建献起,在這個(gè)攔截器中洋访,從其中獲取連接,獲取編解碼器
RealConnection 真是連接谴餐,通過streamAllocation尋找可用連接
HttpCodec Http編解碼
別人詳細(xì)的分析
將獲取到的內(nèi)容傳給后續(xù)的攔截器姻政,獲取到返回之后直接返回給前面的攔截器,沒有做進(jìn)一步的處理岂嗓。

3.5 networkInterceptors

這些是在請求的時(shí)候設(shè)置的攔截器

3.6 CallServerInterceptor

最后一個(gè)攔截器汁展,也是最重要的攔截器,response就是在這個(gè)攔截器中通過網(wǎng)絡(luò)請求獲取到的。

@OverridepublicResponse intercept(Chain chain)throwsIOException {
  RealInterceptorChain realChain = (RealInterceptorChain) chain;
  HttpCodec httpCodec = realChain.httpStream();
  StreamAllocation streamAllocation = realChain.streamAllocation();
  RealConnection connection = (RealConnection) realChain.connection();
  Request request = realChain.request();
  longsentRequestMillis = System.currentTimeMillis();
  //寫入頭部
  httpCodec.writeRequestHeaders(request);
  Response.Builder responseBuilder =null;
  //請求是否有body
  if(HttpMethod.permitsRequestBody(request.method()) && request.body() !=null) {
    // If there's a "Expect: 100-continue" header on the request, wait for a "HTTP/1.1 100
    // Continue" response before transmitting the request body. If we don't get that, return what
    // we did get (such as a 4xx response) without ever transmitting the request body.
    //頭部是否有100-continue食绿,有的話等待response
    if("100-continue".equalsIgnoreCase(request.header("Expect"))) {
      httpCodec.flushRequest();
      responseBuilder = httpCodec.readResponseHeaders(true);
    }

    //沒有100-continue 
    if(responseBuilder ==null) {
      // Write the request body if the "Expect: 100-continue" expectation was met.
      Sink requestBodyOut = httpCodec.createRequestBody(request, request.body().contentLength());
      BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut);
      //寫入body
      request.body().writeTo(bufferedRequestBody);
      bufferedRequestBody.close();
    }else if(!connection.isMultiplexed()) {
      // If the "Expect: 100-continue" expectation wasn't met, prevent the HTTP/1 connection from
      // being reused. Otherwise we're still obligated to transmit the request body to leave the
      // connection in a consistent state.
      streamAllocation.noNewStreams();
    }
  }

  //完成request寫入
  httpCodec.finishRequest();
  if(responseBuilder ==null) {
    //讀取頭部侈咕,并返回response
    responseBuilder = httpCodec.readResponseHeaders(false);
  }
  //創(chuàng)建response
  Response response = responseBuilder
    .request(request)
    .handshake(streamAllocation.connection().handshake())
    .sentRequestAtMillis(sentRequestMillis)
    .receivedResponseAtMillis(System.currentTimeMillis())
    .build();
  
  intcode = response.code();
  //根據(jù)類型更新response屬性
  if(forWebSocket&& code ==101) {
  // Connection is upgrading, but we need to ensure interceptors see a non-null response body.
    response = response.newBuilder()
        .body(Util.EMPTY_RESPONSE)
        .build();
  }else{
    //讀取body
    response = response.newBuilder()
      .body(httpCodec.openResponseBody(response))
      .build();
  }
  
  //請求是否要求關(guān)閉連接
  if("close".equalsIgnoreCase(response.request().header("Connection"))
      ||"close".equalsIgnoreCase(response.header("Connection"))) {
    streamAllocation.noNewStreams();
  }
  
  if((code ==204|| code ==205) && response.body().contentLength() >0) {
      throw newProtocolException(
        "HTTP "+ code +" had non-zero Content-Length: "+     response.body().contentLength());
  }
  return response;
}

繼續(xù)總結(jié)中......

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市器紧,隨后出現(xiàn)的幾起案子耀销,更是在濱河造成了極大的恐慌,老刑警劉巖品洛,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件树姨,死亡現(xiàn)場離奇詭異,居然都是意外死亡桥状,警方通過查閱死者的電腦和手機(jī)帽揪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來辅斟,“玉大人转晰,你說我怎么就攤上這事∈快” “怎么了查邢?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長酵幕。 經(jīng)常有香客問我扰藕,道長,這世上最難降的妖魔是什么芳撒? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任邓深,我火速辦了婚禮,結(jié)果婚禮上笔刹,老公的妹妹穿的比我還像新娘芥备。我一直安慰自己,他們只是感情好舌菜,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布萌壳。 她就那樣靜靜地躺著,像睡著了一般日月。 火紅的嫁衣襯著肌膚如雪袱瓮。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天爱咬,我揣著相機(jī)與錄音懂讯,去河邊找鬼。 笑死台颠,一個(gè)胖子當(dāng)著我的面吹牛褐望,可吹牛的內(nèi)容都是我干的勒庄。 我是一名探鬼主播,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼瘫里,長吁一口氣:“原來是場噩夢啊……” “哼实蔽!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起谨读,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤局装,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后劳殖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體铐尚,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年哆姻,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了宣增。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,872評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡矛缨,死狀恐怖爹脾,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情箕昭,我是刑警寧澤灵妨,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站落竹,受9級特大地震影響泌霍,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜述召,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一朱转、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧桨武,春花似錦肋拔、人聲如沸锈津。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽琼梆。三九已至性誉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間茎杂,已是汗流浹背错览。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留煌往,地道東北人倾哺。 一個(gè)月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓轧邪,卻偏偏與公主長得像,于是被迫代替她去往敵國和親羞海。 傳聞我的和親對象是個(gè)殘疾皇子忌愚,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,876評論 2 361

推薦閱讀更多精彩內(nèi)容

  • 前言 用OkHttp很久了,也看了很多人寫的源碼分析却邓,在這里結(jié)合自己的感悟硕糊,記錄一下對OkHttp源碼理解的幾點(diǎn)心...
    Java小鋪閱讀 1,523評論 0 13
  • 這篇文章主要講 Android 網(wǎng)絡(luò)請求時(shí)所使用到的各個(gè)請求庫的關(guān)系,以及 OkHttp3 的介紹腊徙。(如理解有誤简十,...
    小莊bb閱讀 1,166評論 0 4
  • 用OkHttp很久了,也看了很多人寫的源碼分析撬腾,在這里結(jié)合自己的感悟螟蝙,記錄一下對OkHttp源碼理解的幾點(diǎn)心得。 ...
    藍(lán)灰_q閱讀 4,305評論 4 34
  • 流程分析 我們從一個(gè)簡單的 HTTP 請求開始: 上面的代碼將會(huì)發(fā)起兩個(gè)簡單的 HTTP 請求时鸵,請求流程如下圖所示...
    張可_閱讀 896評論 0 2
  • 很多人當(dāng)心事滿滿的時(shí)候胶逢,會(huì)習(xí)慣仰起頭,看著藍(lán)天白云饰潜,想著什么初坠,云就是什么形狀的,總覺得鳥會(huì)說話彭雾,太陽在對你笑碟刺,...
    若愛一往如初閱讀 170評論 0 0