OKhttp源碼學(xué)習(xí)(三)—— Request, RealCall

Request,RealCall 分析

源碼地址:https://github.com/square/okhttp

上一篇 對okHttpClient做了簡單的分析床玻,現(xiàn)在就對另外兩個比較重要的類進(jìn)行學(xué)習(xí)分析(Request, RealCall)卿捎,這兩個類是我們調(diào)用時候的請求相關(guān)的類骡苞。
這里做簡單的學(xué)習(xí)分析,便于后面流程的理解伟墙。

Request

Request這個請求類,同樣的使用了Bulider模式滴铅,不過這個比OkhttpClient簡單多了戳葵,主要用于添加請求需要的一些基本屬性。

        final HttpUrl url;
        final String method;
        final Headers headers;
        final RequestBody body;
        final Object tag;
      Request(Builder builder) {
        this.url = builder.url;
        this.method = builder.method;
        this.headers = builder.headers.build();
        this.body = builder.body;
        this.tag = builder.tag != null ? builder.tag : this;
    }
  1. url汉匙,傳入的String ,經(jīng)過進(jìn)一步加工處理拱烁,還有一些錯誤的判斷,最后轉(zhuǎn)換為HttpUrl的類噩翠。
  2. method戏自,確定請求的類型,默認(rèn)使用GET绎秒。支持http 基本的請求方式浦妄。
  3. headers, 我們可以自定義添加對應(yīng)的Header , 最后轉(zhuǎn)換成Header類。也可以對其中的Header進(jìn)行操作见芹。
  4. body剂娄,請求的實體,RequestBody 玄呛,傳輸?shù)腸ontentType阅懦,把傳輸?shù)腸ontent,進(jìn)行簡單處理徘铝。
  5. tag耳胎,標(biāo)簽惯吕。

RealCall

RealCall, 實現(xiàn)了Call接口,也是OkHttp里面唯一一個Call的實現(xiàn)類怕午。

1. RealCall幾個重要的變量:
    final OkHttpClient client;
    final RetryAndFollowUpInterceptor retryAndFollowUpInterceptor;
    final Request originalRequest;

client :上節(jié)中已經(jīng)對其進(jìn)行介紹废登,RealCall 在構(gòu)造方法中以參數(shù)的形式傳進(jìn)來,供內(nèi)部使用郁惜。

retryAndFollowUpInterceptor : 在第一節(jié)中也做過簡單介紹堡距,是一個攔截器,處理重試兆蕉,網(wǎng)絡(luò)錯誤羽戒,取消請求,以及請求重定向的一些操作虎韵。(后面會詳細(xì)學(xué)習(xí)分析)

**originalRequest : ** 原始的請求類易稠。

2. RealCall里面有個幾個重要的方法:

execute() 同步請求

  @Override 
  public Response execute() throws IOException {
    synchronized (this) {
     if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
     }
    captureCallStackTrace();
    try {
      client.dispatcher().executed(this);
      Response result = getResponseWithInterceptorChain();
      if (result == null) throw new IOException("Canceled");
      return result;
    } finally {
      client.dispatcher().finished(this);
    }
  }

發(fā)起的一個同步的請求,如果重復(fù)調(diào)用會拋出異常包蓝。
captureCallStackTrace()是用來跟蹤調(diào)用棧的信息的驶社。
后面就是把這個Call 加入到client的調(diào)度器里面,進(jìn)行相應(yīng)的線程管理测萎。
最后就是調(diào)用getResponseWithInterceptorChain衬吆,這個在第一節(jié)做過分析,就是經(jīng)過一堆攔截器绳泉,然后得到結(jié)果逊抡。

enqueue()異步請求

  @Override 
 public void enqueue(Callback responseCallback) {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace();
    client.dispatcher().enqueue(new AsyncCall(responseCallback));
  }

發(fā)起異步請求。如果重復(fù)調(diào)用會拋出異常零酪。
captureCallStackTrace()同樣是用來跟蹤調(diào)用棧的信息的冒嫡。
接下來,會新建一個AsyncCall四苇,這個AsyncCall其實是一個Runnable線程孝凌,簡單過一下這個AsyncCall的代碼:

  final class AsyncCall extends NamedRunnable {
   // 回調(diào)
    private final Callback responseCallback;

    AsyncCall(Callback responseCallback) {
      super("OkHttp %s", redactedUrl());
      this.responseCallback = responseCallback;
    }

    String host() {
      return originalRequest.url().host();
    }

    Request request() {
      return originalRequest;
    }

    RealCall get() {
      return RealCall.this;
    }

    //run的時候調(diào)用的方法
    @Override protected void execute() {
      boolean signalledCallback = false;
      try {
        Response response = getResponseWithInterceptorChain();
        if (retryAndFollowUpInterceptor.isCanceled()) {
          signalledCallback = true;
          responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
        } else {
          signalledCallback = true;
          responseCallback.onResponse(RealCall.this, response);
        }
      } catch (IOException e) {
        if (signalledCallback) {
          // Do not signal the callback twice!
          Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
        } else {
          responseCallback.onFailure(RealCall.this, e);
        }
      } finally {
        client.dispatcher().finished(this);
      }
    }
  }

在execute的調(diào)用中,其實和同步調(diào)用時一樣的月腋,只是這個是在異步線程中進(jìn)行蟀架。

最后這個新建的AsyncCall ,同樣會通過client 添加到dispatcher當(dāng)中,但是值得注意的是榆骚,同步和異步片拍,其實是添加到dispatcher不同的List當(dāng)中,進(jìn)行管理的妓肢。

getResponseWithInterceptorChain()
調(diào)用一系列的攔截器捌省,得到最終的結(jié)果,在第一節(jié)中對此做過解析碉钠,可以參考第一節(jié)最后的部分纲缓。這里就不做過多的說明卷拘,具體每個攔截器的作用,在后面會做學(xué)習(xí)分析祝高。

cancel()
調(diào)用里面比較簡單栗弟,就是通過retryAndFollowUpInterceptor這個攔截器去對請求進(jìn)行取消。對于正在執(zhí)行的call 進(jìn)行取消工闺,但是對于已經(jīng)是在讀寫數(shù)據(jù)階段的請求無法取消横腿,而且會拋出異常。

  @Override public void cancel() {
    retryAndFollowUpInterceptor.cancel();
  }

總結(jié)

Request和RealCall, 在發(fā)起請求階段斤寂,是兩個重要的類。Request主要是接收了調(diào)用者的數(shù)據(jù)并進(jìn)行加工處理揪惦;RealCall主要提供方法遍搞,進(jìn)行同步或者異步的調(diào)用請求,還有就是取消請求的方法器腋。

對于okhttp的整體以及前期的初始化的一些類也有所了解溪猿,接下來就是對每個攔截器進(jìn)行解剖學(xué)習(xí)了。

系列:
OKhttp源碼學(xué)習(xí)(一)—— 基本請求流程
OKhttp源碼學(xué)習(xí)(二)—— OkHttpClient
OKhttp源碼學(xué)習(xí)(四)——RetryAndFollowUpInterceptor攔截器分析
OKhttp源碼學(xué)習(xí)(五)—— BridgeInterceptor
OKhttp源碼學(xué)習(xí)(六)—— CacheInterceptor攔截器
OKhttp源碼學(xué)習(xí)(七)—— ConnectInterceptor攔截器
OKhttp源碼學(xué)習(xí)(八)——CallServerInterceptor攔截器
OKhttp源碼學(xué)習(xí)(九)—— 任務(wù)管理(Dispatcher)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末纫塌,一起剝皮案震驚了整個濱河市诊县,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌措左,老刑警劉巖依痊,帶你破解...
    沈念sama閱讀 221,888評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異怎披,居然都是意外死亡胸嘁,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評論 3 399
  • 文/潘曉璐 我一進(jìn)店門凉逛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來性宏,“玉大人,你說我怎么就攤上這事状飞『潦ぃ” “怎么了?”我有些...
    開封第一講書人閱讀 168,386評論 0 360
  • 文/不壞的土叔 我叫張陵诬辈,是天一觀的道長酵使。 經(jīng)常有香客問我,道長焙糟,這世上最難降的妖魔是什么凝化? 我笑而不...
    開封第一講書人閱讀 59,726評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮酬荞,結(jié)果婚禮上搓劫,老公的妹妹穿的比我還像新娘瞧哟。我一直安慰自己,他們只是感情好枪向,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,729評論 6 397
  • 文/花漫 我一把揭開白布勤揩。 她就那樣靜靜地躺著,像睡著了一般秘蛔。 火紅的嫁衣襯著肌膚如雪陨亡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,337評論 1 310
  • 那天深员,我揣著相機(jī)與錄音负蠕,去河邊找鬼。 笑死倦畅,一個胖子當(dāng)著我的面吹牛遮糖,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播叠赐,決...
    沈念sama閱讀 40,902評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼欲账,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了芭概?” 一聲冷哼從身側(cè)響起赛不,我...
    開封第一講書人閱讀 39,807評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎罢洲,沒想到半個月后踢故,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,349評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡惹苗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,439評論 3 340
  • 正文 我和宋清朗相戀三年畴椰,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鸽粉。...
    茶點(diǎn)故事閱讀 40,567評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡斜脂,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出触机,到底是詐尸還是另有隱情帚戳,我是刑警寧澤,帶...
    沈念sama閱讀 36,242評論 5 350
  • 正文 年R本政府宣布儡首,位于F島的核電站片任,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏蔬胯。R本人自食惡果不足惜对供,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,933評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧产场,春花似錦鹅髓、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至确徙,卻和暖如春醒串,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背鄙皇。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評論 1 272
  • 我被黑心中介騙來泰國打工芜赌, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人伴逸。 一個月前我還...
    沈念sama閱讀 48,995評論 3 377
  • 正文 我出身青樓缠沈,卻偏偏與公主長得像,于是被迫代替她去往敵國和親违柏。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,585評論 2 359

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