第七天(okhttp主線流程源碼)

Okhttp源碼主要涉及到的到有以下幾個類

OKHttpClient

Request

Response

Call

Callback

簡單用法

        OkHttpClient client = new OkHttpClient.Builder().build();

        Request  request = new Request.Builder().url("https://www.baidu.com").build();
        Call call = client.newCall(request);
        
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.body()!=null) {
                    String body =  response.body().string();
                }
            }
        });

分析: 當client.newCall(request)的時候

  @Override public Call newCall(Request request) {
    return RealCall.newRealCall(this, request, false /* for web socket */);
  }
  static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
    // Safely publish the Call instance to the EventListener.
    RealCall call = new RealCall(client, originalRequest, forWebSocket);
    call.eventListener = client.eventListenerFactory().create(call);
    return call;
  }

RealCall是Call的實現類,所以執行Call的方法其實都是在RealCall中實現的

 

再來分析call.enqueue()


  @Override public void enqueue(Callback responseCallback) {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");//防止一個call執行二次
      executed = true;
    }
    captureCallStackTrace();
    eventListener.callStart(this);
    client.dispatcher().enqueue(new AsyncCall(responseCallback));
  }

從上面代碼可以看出,最後是將Callback封裝到了AsyncCall裏面,並將其放到到dispatcher分發器的執行,看Dispathcher的方法

  synchronized void enqueue(AsyncCall call) {
    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
      runningAsyncCalls.add(call);
      executorService().execute(call);
    } else {
      readyAsyncCalls.add(call);
    }
  }

AsyncCall是什麼

AsyncCall是RealCall的一個內部類,繼承於

NamedRunnable,面NamedRunnable實現了Runnable,

所以AsyncCall就是一個Runnable

每當線程池執行AsyncCall這個任務時,就會執行其的run方法也就是NameRunnable的一個抽象方法

execute();由子類AsyncCall來實現的,也就是下面代碼
@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 {
          eventListener.callFailed(RealCall.this, e);
          responseCallback.onFailure(RealCall.this, e);
        }
      } finally {
        client.dispatcher().finished(this);
      }
    }

這裏有個finally運用的是非常的巧妙,不管成功還是失敗都會執行,下面代碼可以看也,每當一個任務執行完會進行一些判斷,並從隊列中取任務並繼續執行下去.

  private void promoteCalls() {
    if (runningAsyncCalls.size() >= maxRequests) return; // Already running max capacity.
    if (readyAsyncCalls.isEmpty()) return; // No ready calls to promote.

    for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
      AsyncCall call = i.next();

      if (runningCallsForHost(call) < maxRequestsPerHost) {
        i.remove();
        runningAsyncCalls.add(call);
        executorService().execute(call);
      }

      if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity.
    }
  }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章