OKHttp3源碼解析

總體流程:

okHttpClient = new OkHttpClient.Builder()
        .addInterceptor(new TokenInterceptor())
        .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
        .build();

通過builder模式建造okhttpclient,然後通過request把請求參數封裝起來,Requset構造函數如下:

Request(Builder builder) {
  this.url = builder.url;
  this.method = builder.method;
  this.headers = builder.headers.build();
  this.body = builder.body;
  this.tags = Util.immutableMap(builder.tags);
}

然後okhttpClient通過newCall()把request對象轉換成Call對象

@Override public Call newCall(Request request) {
  return RealCall.newRealCall(this, request, false /* for web socket */);
}

真正執行的是RealCall,然後通過同步方法execute()或異步方法enqueue()去執行網絡請求;

在execute()方法中:

@Override public Response execute() throws IOException {
  synchronized (this) {
    if (executed) throw new IllegalStateException("Already Executed");
    executed = true;
  }
  captureCallStackTrace();
  timeout.enter();
  eventListener.callStart(this);
  try {
    //標記該call正在執行
    client.dispatcher().executed(this);
    Response result = getResponseWithInterceptorChain();
    if (result == null) throw new IOException("Canceled");
    return result;
  } catch (IOException e) {
    e = timeoutExit(e);
    eventListener.callFailed(this, e);
    throw e;
  } finally {
    client.dispatcher().finished(this);
  }
}

現在執行結果是在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));
  //index=0
  Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
      originalRequest, this, eventListener, client.connectTimeoutMillis(),
      client.readTimeoutMillis(), client.writeTimeoutMillis());

  return chain.proceed(originalRequest);
}

攔截器是用了責任鏈模式,下面看RealInterceptorChain類中的chain.proceed(originalRequest);

Interceptor.Chain是接口,RealInterceptorChain是實現類
public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
    RealConnection connection) throws IOException {
  if (index >= interceptors.size()) throw new AssertionError();

  calls++;

  // If we already have a stream, confirm that the incoming request will use it.
  if (this.httpCodec != null && !this.connection.supportsUrl(request.url())) {
    throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
        + " must retain the same host and port");
  }

  // If we already have a stream, confirm that this is the only call to chain.proceed().
  if (this.httpCodec != null && calls > 1) {
    throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
        + " must call proceed() exactly once");
  }

  // Call the next interceptor in the chain.
  RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
      connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
      writeTimeout);
//這裏是從攔截器list中獲取一個攔截器
  Interceptor interceptor = interceptors.get(index);
  //然後調用攔截器的intercept(next)方法,並把從下一個攔截器開始的鏈當參數傳進去
  Response response = interceptor.intercept(next);

  // Confirm that the next interceptor made its required call to chain.proceed().
  if (httpCodec != null && index + 1 < interceptors.size() && next.calls != 1) {
    throw new IllegalStateException("network interceptor " + interceptor
        + " must call proceed() exactly once");
  }

  // Confirm that the intercepted response isn't null.
  if (response == null) {
    throw new NullPointerException("interceptor " + interceptor + " returned null");
  }

  if (response.body() == null) {
    throw new IllegalStateException(
        "interceptor " + interceptor + " returned a response with no body");
  }

  return response;
}

第一個攔截器是我們自定義的攔截器,下面看我們自定義的攔截器:

private class TokenInterceptor implements Interceptor {


    @Override
    public Response intercept(Chain chain) throws IOException {
           ....省略一些代碼
            Request request = chain.request().newBuilder()
                    .header("auth-token", PreferencesUtil.getString( "accessToken") )
                    .build();
            //繼續調用chain.proceed(request)
            Response response = chain.proceed(request);
            //Headers requestHeaders= response.networkResponse().request().headers();
            //Log.d("simu4", "intercept: requestHeaders="+requestHeaders.toString());
            MediaType mediaType = response.body().contentType();
            Logger.i("response = "+response.toString());

            if (isTokenExpired(response)) {
                //同步請求方式,獲取最新的Token
                Log.e("NetworkRequest.simu", "靜默自動刷新Token後 重新請求數據");
                //同步請求方式,獲取最新的Token
                String newSession = getNewToken();
                //使用新的Token,創建新的請求
                if (null != newSession && newSession.length() > 0) {
                    Request newRequest = chain.request()
                            .newBuilder()
                            .header("auth-token", newSession)
                            .build();
                    //重新請求上次的接口
                    return chain.proceed(newRequest.newBuilder().build());
                }

            }
            //如果token正常返回結果
            return response.newBuilder().body(ResponseBody.create(mediaType, resultStr)).build();
        }else {
            Request request = chain.request().newBuilder()
                    .header("Authorization", "Bearer "+(PreferencesUtil.getString( "accessToken") == null ? WindConstants.FROM_ANDROID : PreferencesUtil.getString( "accessToken")))
                    .build();

            Logger.i("request toString="+request.toString());
            Response response = chain.proceed(request);
            //Headers requestHeaders= response.networkResponse().request().headers();
            //Log.d("simu4", "intercept: requestHeaders="+requestHeaders.toString());
            MediaType mediaType = response.body().contentType();
            Logger.i("response = "+response.toString());

            if (isTokenExpired(response)) {
                //同步請求方式,獲取最新的Token
                Log.e("NetworkRequest.simu", "靜默自動刷新Token後 重新請求數據");
                //同步請求方式,獲取最新的Token
                String newSession = getNewToken();
                //使用新的Token,創建新的請求
                if (null != newSession && newSession.length() > 0) {
                    Request newRequest = chain.request()
                            .newBuilder()
                            .header("Authorization", "Bearer "+newSession)
                            .build();
                    //重新請求上次的接口
                    return chain.proceed(newRequest.newBuilder().build());
                }

            }
            //如果token正常返回結果
            return response.newBuilder().body(ResponseBody.create(mediaType, resultStr)).build();
        }
    }

從上面代碼可以看到繼續回調chain.proceed(request);此時的chain是從下一個攔截器開始的,因此繼續回調RealInterceptorChain類中的process(),直到有一層攔截器返回結果,然後向上傳遞結果

 

異步執行:

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

Dispatcher中的enqueue()

void enqueue(AsyncCall call) {
  synchronized (this) {
    readyAsyncCalls.add(call);
  }
  promoteAndExecute();
}
private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();

把call放入readyAsyncCalls中,

private boolean promoteAndExecute() {
  assert (!Thread.holdsLock(this));

  List<AsyncCall> executableCalls = new ArrayList<>();
  boolean isRunning;
  synchronized (this) {
    for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
      AsyncCall asyncCall = i.next();

      if (runningAsyncCalls.size() >= maxRequests) break; // Max capacity.
      if (runningCallsForHost(asyncCall) >= maxRequestsPerHost) continue; // Host max capacity.

      i.remove();
      executableCalls.add(asyncCall);
      runningAsyncCalls.add(asyncCall);
    }
    isRunning = runningCallsCount() > 0;
  }

  for (int i = 0, size = executableCalls.size(); i < size; i++) {
    AsyncCall asyncCall = executableCalls.get(i);
    asyncCall.executeOn(executorService());
  }

return isRunning; }

調用asyncCall.executeOn(),把asyncCall放在線程池中執行

void executeOn(ExecutorService executorService) {
  assert (!Thread.holdsLock(client.dispatcher()));
  boolean success = false;
  try {
    executorService.execute(this);
    success = true;
  } catch (RejectedExecutionException e) {
    InterruptedIOException ioException = new InterruptedIOException("executor rejected");
    ioException.initCause(e);
    eventListener.callFailed(RealCall.this, ioException);
    responseCallback.onFailure(RealCall.this, ioException);
  } finally {
    if (!success) {
      client.dispatcher().finished(this); // This call is no longer running!
    }
  }
}
然後看AsyncCall ,它繼承與NamedRunnable,NamedRunnable是一個抽象類,它實現了Runnable接口,在NamedRunnable的run方法中調用了execute(),execute()是抽象方法,因此會回調AsyncCall 中的execute()
@Override protected void execute() {
  boolean signalledCallback = false;
  timeout.enter();
  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) {
    e = timeoutExit(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);
  }
}

仍然是調用getResponseWithInterceptorChain(),後面與同步方法一樣,只不過是放在線程池中執行,線程池如下:

public synchronized ExecutorService executorService() {
  if (executorService == null) {
    executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
        new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
  }
  return executorService;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章