Okhttp同步請求原始碼分析

codeGoogle發表於2019-01-31

進階android,OKhttp原始碼分析——同步請求的原始碼分析

OKhttp是我們經常用到的框架,作為開發者們,我們不單單要學會靈活使用,還要知道他的原始碼是如何設計的。

今天我們來分析一下OKhttp 同步請求的執行流程和原始碼分析

so,老樣子,我們先來一張圖

從上圖可以看出,不管是同步請求還是非同步請求,我們都需要建立一個OKhttpClient物件,用到的是build構造者模式,建立Request物件,然後再OKhttpClient的newCall方法和Request來封裝我們的call物件。建立我們的實際請求的call物件,從上圖可以看到,對於同步請求,我們呼叫的是excute方法,非同步請求呼叫的是equeue方法。

我們看一下做簡單使用

OkHttpClient okHttpClient = new  OkHttpClient.Builder()
                .readTimeout(10, TimeUnit.SECONDS)
                .build();
        Request request = new Request.Builder().url("https://blog.csdn.net/androidstarjack").build();

        Call call = okHttpClient.newCall(request);
        try {
            call.execute();//同步請求
            call.enqueue(new Callback() {//非同步請求
                @Override
                public void onFailure(Call call, IOException e) {

                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {

                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }

複製程式碼

我們先看一下okhttp的build

首先我們通過原始碼可以看出,okhttp的建立時通過build方法來建立的,其中初始化了一些事情,比如建立一個dispatcher攔截器,和一個連線池,連線池只要是連結狀態的儲存以及複用。build是要是建立 okhttp是所需要的引數。

在建立Request建立的時候也是用構造者模式進行建立的,原始碼如下:

  Builder(Request request) {
      this.url = request.url;
      this.method = request.method;
      this.body = request.body;
      this.tag = request.tag;
      this.headers = request.headers.newBuilder();
    }
複製程式碼

request的build構造裡面初始化了一些請求的URL,請求方法哈請求頭等請求報文的一些資訊。

Call物件 是通過他的父親RealCall來完成的。

Call物件持有了Okhttp 和Request兩個物件,同時呢還建立了一個快取攔截器RetryAndFollowUpInterceptor,用於所需要的重定向操作。

通過呼叫okhttpClient的newCAll來完成CALL的新建,進行相應的操作

緊接著呼叫execute方法來完成同步請求!

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

複製程式碼

//布林值executed表示一個okhttp請求只能執行執行一次,然後開啟捕捉一些錯誤堆疊資訊,點用一個eventListener監聽方法, 接卸來是呼叫分發器的executed方法。這才是重中之重。

...
 client.dispatcher().executed(this);
...

複製程式碼

client.dispatcher返回一個分發器。然後通過分發器來執行操作:

在同步請求中,呼叫executed方法,很簡單酒吧這個Call物件新增到佇列當中。

Dispatcher的作用主要是維持call請求發給他 的狀態,同時維護了一個執行緒池,開啟了網路請求。

從原始碼中我們可以看到Dispatcher

這幾個請求佇列代表著不同狀態下的請求情況。

緊接著通過攔截器鏈依次呼叫執行操作。 最後還呼叫了Finish方法

注意第三個引數,為false,這個方法的主要作用就是移除當前的請求,如果不能移除的話,返回異常,我們可以注意到,同步請求不需要呼叫promoteCalls,只有在非同步請求的時候才會呼叫到,這個方法以後我們在講。

最後判斷,正在將要執行的請求佇列集合為0並且閒呼叫的回撥不為null時,呼叫其run方法。此時,同步方法執行完成。

閱讀更多

2018年技術文章彙總

NDK專案實戰—高仿360手機助手之解除安裝監聽

(Android)面試題級答案(精選版)

如果對技術開發比較感興趣,歡迎關注公眾號:終端研發部。一起交流技術,進階!

相關文章