OKHttp源码解析

一、总结

一、网络请求流程

OkHttp分同步网络请求和异步网络请求。

第一步:通过建造者模式来创建OkHttpClient对象。会创建默认的参数。我们也可以在这里传入自己配置的构建参数,比如设置超时时间、自定义拦截器、

❌创建OkHttpClient客户端对象,OkHttpClient通过建造者模式来封装OkHttpClient初始化需要的参数,主要进行了dispatcher、connectionPool(连接池)等创建。❌

第二步:通过建造者模式创建了Request,这这里面主要封装了。创建Request对象,通过建造者模式封装请求报文信息、请求地址、请求方法和请求头,默认请求方法为get。

第三步:通过OkHttpClient和request创建realCall。

第四步:如果是同步请求,会调用realCall的execute方法。

第五步:如果是异步请求,会调用realCall的enqueue方法。此时我们要传入Callback,用于回调成功或失败。

二、同步请求

如果是同步请求,会通过dispatcher将call添加到runningSyncCalls同步请求队列中。然后调用拦截器链方法获得response。请求结束后,从同步请求队列移除这个同步请求。

三、异步请求

如果是异步请求,首先创建AsyncCall对象,里面封装了realCall。AsyncCall实现了Runnable。然后把AsyncCall添加到readyAsyncCalls缓存等待的请求队列中。然后调用promoteAndExecute方法,这个方法的作用是调整异步请求队列和缓存请求队列。遍历异步缓存队列,然后判断正在执行的异步请求队列runningAsyncCalls的size是否小于64或同host的小于5,如果满足条件将任务添加到正在执行的异步请求队列中,然后从异步缓存队列中将任务移除。然后调用executorService线程池执行AsyncCall,之后调用AsyncCall的run方法。在run方法中调用拦截器链方法获得response。任务请求结束后,从异步请求队列移除当前请求,之后继续调用promoteAndExecute方法。

四、调用executorService线程池执行AsyncCall

调用executorService线程池执行AsyncCall。Runnable实现了Runnable,所以会调用run方法。然后执行AsyncCall的execute方法。然后创建RealInterceptorChain拦截器链,将我们自定义的ApplicationInterceptor和五大拦截器重试拦截器、桥接连接器、缓存拦截器、连接拦截器和网络请求拦截器和NetwrokInterceptor添加到集合中。然后通过链式调用顺序调用拦截器的intercept方法获取response,然后将response返回给上一个拦截器。

五、Application Interceptor

Application Interceptor 是第一个执行的拦截器,Application Interceptor 适用于在请求前统一添加一些公共参数,例如在添加 APP 的版本号,用户 ID ,手机版本号,运营商类型等参数。或者对响应体的数据进行 json 转化等操作。比如DebugInterceptor,在网络请求是拦截请求,返回我们自定义的json数据,方便数据联调。他的原理是,这是拦截器链走的第一个方法,我们判断是否对请求进行拦截,如果拦截的话,终止链式调用,直接将我们从本地文件读取的json作为response返回。

六、RetryAndFollowUpInterceptor

RetryAndFollowUpInterceptor重试和重定向拦截器,开启一个while (true) 循环,在死循环中会调用接下来的拦截器方法获取网络请求,如果请求失败,会进行重试请求。如果重试次数超过20次,会终止循环,抛出异常。

七、BridgeInterceptor

BridgeInterceptor桥接适配拦截器,在这里将我们的request转化为可以进行网络请求的request,添加头部信息比如Content-Type、Content-Length、Transfer-Encoding、Host、Connection=”Keep-Alive”保持长连接,Accept-Encoding、Cookie、User-Agent。然后调用拦截器链方法获取网络数据,然后对response进行解析,比如变成我们可以使用的response。比如gzip解压缩,responseCode是否为200等。

八、CacheInterceptor

CacheInterceptor缓存拦截器,根据request从磁盘缓存DiskLruCache中获取缓存,如果网络请求和缓存为空会抛出504异常。如果网络请求为空,缓存不为空会直接返回缓存。

否则进行网络请求,调用拦截器链方法获取response,如果缓存不为空,会对responseCode进行判断,如果等于304直接返回缓存,然后更新缓存数据。如果缓存为空,会保存缓存。也会将缓存中无效的request对应的缓存删除。

九、ConnectInterceptor

ConnectInterceptor网络链接拦截器,在这里会创建exchange,exchange会携带request和response。在这里我们会获取网络链接,首先判断是否有合适的链接,如果没有我们连接池取,复用已有的链接。如果还是没有,我们会自己创建一个链接RealConnection。然后调用RealConnection的connect方法,进行TCP 和 TLS 握手。

十、networkInterceptor

接下来,就是我们自定义的networkInterceptors,在这里可以获取到最终发送请求的 request ,也可以获取到真正发生网络请求回来的 response 响应

十一、CallServerInterceptor

CallServerInterceptor:对我们的请求头和请求体进行写入,然后调用Okio进行真正的IO流操作。之后读取服务器返回的response。然后返回上一级拦截器。

十二、调用dispatcher的finish方法

网络请求成功后,再次调用promoteAndExecute方法,从异步请求队列中将当前请求移除,对异步缓存队列和异步请求队列进行调整,判断是否进行下个任务。

二、Interceptor和NetwrokInterceptor区别

  • Application Interceptor 因为是第一个被执行的拦截器,因此它有权决定了是否要调用其他拦截,也就是 Chain.proceed() 方法是否要被执行。适用于在请求前统一添加一些公共参数,例如在添加 APP 的版本号,用户 ID ,手机版本号,运营商类型等参数。或者对响应体的数据进行 json 转化等操作。比如DebugInterceptor、添加请求头信息、对response统一进行处理。
  • NetworkInterceptor:因为 NetworkInterceptor 是排在第 6 个拦截器中,可以获取到最终发送请求的 request ,也可以获取到真正发生网络请求回来的 response 响应。对于从缓存获取的 response 则不会去触发 NetworkInterceptor 。因为响应直接从 CacheInterceptor 返回了。可以使用日志拦截器。

二、源码解析,以异步请求为主。

1、请求代码

作用:

(1)创建OkHttpClient客户端对象

(1)通过建造者模式创建了Request

(1)执行realCall的enqueue方法

//1.新建OKHttpClient客户端
val okHttpClient = OkHttpClient.Builder().build()
//2、新建一个Request对象
val request = Request.Builder().url("").build()
val realCall = okHttpClient.newCall(request)
realCall.enqueue(object : Callback{
   override fun onFailure(call: Call, e: IOException) {
   }
   override fun onResponse(call: Call, response: Response) {
   }
})

2、调用RealCall的enqueue方法

作用:

(1)传入了Callback接口对象,用于接口回调。

(2)创建AsyncCall对象,里面封装了realCall。AsyncCall实现了Runnable。线程池会执行AsyncCall,调用AsyncCall的run方法。

(3)调用dispatcher的enqueue方法,

@Override public void enqueue(Callback responseCallback) {
  //1、加了锁
  synchronized (this) {
  //2、只能执行一次,如果再次执行会抛出异常
    if (executed) throw new IllegalStateException("Already Executed");
    executed = true;
  }
  transmitter.callStart();
  //3、重点在这里
  client.dispatcher().enqueue(new AsyncCall(responseCallback));
}

3、调用dispatcher的enqueue方法

1)作用:

(1)把AsyncCall添加到readyAsyncCalls异步缓存请求队列中,

(2)调用promoteAndExecute方法。

void enqueue(AsyncCall call) {
  synchronized (this) {
  //1、把call添加到异步缓存请求队列中
    readyAsyncCalls.add(call);
  //省略部分代码
  、、、、
  //2、调用此方法
  promoteAndExecute();
}

2)Dispatcher的作用

Dispatcher管理同步和异步请求,维护了三个任务队列,并维护一个线程池用于执行异步请求,让网络请求变得更高效。

readyAsyncCalls:缓存等待的请求队列

runningAsyncCalls:正在执行的异步请求队列。

runningSyncCalls:正在执行的同步请求队列。

executorService:线程池

3)ExecutorService线程池

ExecutorService executorService= new ThreadPoolExecutor();

各参数的意义:

ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,

BlockingQueue workQueue, ThreadFactory threadFactory)

  • corePoolSize 核心线程数,核心线程会一直存活,即使没有任务需要处理。
  • maxPoolSize 线程池允许最大的线程数量。
  • keepAliveTime 当线程空闲时间达到 keepAliveTime,该线程会退出,直到线程数量等于 corePoolSize。如果allowCoreThreadTimeout 设置为 true,则所有线程均会退出直到线程数量为0。
  • allowCoreThreadTimeout 是否允许核心线程空闲keepAliveTime退出,默认值为false。
  • workQueue 任务队列。pool.execute(runnable) 提交的 task都 会放到workQueue

    4、调用promoteAndExecute方法。

作用:

这个方法的作用是调整异步缓存队列和异步请求队列。通过判断,把任务添加异步请求队列。然后executorService线程池执行AsyncCall的execute方法。

(1)遍历readyAsyncCalls,获取call

(2)判断正在执行的异步请求队列runningAsyncCalls的size是否小于64或同host的小于5,如果满足条件将call添加到正在执行的异步请求队列中,把异步缓存请求队列中的call移除

(3)调用asyncCall.executeOn(executorService())方法

private boolean promoteAndExecute() {
  assert (!Thread.holdsLock(this));
  List<AsyncCall> executableCalls = new ArrayList<>();
  boolean isRunning;
  synchronized (this) {
  //1、遍历异步缓存请求队列
    for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
      AsyncCall asyncCall = i.next();
     //2、判断异步请求队列的size是否大于64
      if (runningAsyncCalls.size() >= maxRequests) break; // Max capacity.
       //3、判断Host是否大于5
      if (asyncCall.callsPerHost().get() >= maxRequestsPerHost) continue; // Host max capacity.
      //4、如果满足上述两个条件,从异步缓存请求队列移除call
      i.remove();
      asyncCall.callsPerHost().incrementAndGet();
      executableCalls.add(asyncCall);
      //5、把call添加到异步请求队列中
      runningAsyncCalls.add(asyncCall);
    }
    isRunning = runningCallsCount() > 0;
  }
  for (int i = 0, size = executableCalls.size(); i < size; i++) {
    AsyncCall asyncCall = executableCalls.get(i);
    //6、调用asyncCall的executeOn方法。
    asyncCall.executeOn(executorService());
  }
  return isRunning;
}

5、调用 asyncCall.executeOn

executeOn作用:

(1)executeOn方法,会调用 executorService.execute(this)方法和dispatcher().finished(this);

(2)executorService.execute(this)方法会利用executorService线程池执行AsyncCall。然后会调用AsyncCall的run方法。在run方法中接着调用拦截器链方法,进行网络数据的获取

(3)dispatcher().finished(this);作用是请求结束后,从异步请求队列移除当前请求,再次调用promoteAndExecute方法,

void executeOn(ExecutorService executorService) {
  、、、
  boolean success = false;
  try {
  //1、调用executorService线程池的execute方法,这个方法会调用AsyncCall的run方法
    executorService.execute(this);
    success = true;
  } catch (RejectedExecutionException e) {
    、、、
     //如果有异常,回调onFailure方法
    responseCallback.onFailure(RealCall.this, ioException);
  } finally {
    if (!success) {
     //2、最后,调用dispatcher的finished方法。
      client.dispatcher().finished(this); // This call is no longer running!
    }
  }
}

6、调用 executorService.execute(this);

作用:

executorService是线程池,执行AsyncCall。AsyncCall继承了Runnable,会执行run方法。在run方法中,调用了execute方法。所以当前执行到AsyncCall的execute方法

(1)调用getResponseWithInterceptorChain方法,通过链式调用拦截器获得response,然后回调给responseCallback的onResponse方法。

(2)调用dispatcher的finish方法,从当前队列移除任务,并判断是否执行队列中的下个任务。

@Override protected void execute() {
 、、、
  try {
  //1、调用拦截器链方法
    Response response = getResponseWithInterceptorChain();
    signalledCallback = true;
    responseCallback.onResponse(RealCall.this, response);
  } catch (IOException e) {
    if (signalledCallback) {
     、、、
      responseCallback.onFailure(RealCall.this, e);
  } catch (Throwable t) {
    cancel();
  、、、
      responseCallback.onFailure(RealCall.this, canceledException);
    }
    throw t;
  } finally {
  //最后执行dispatcher的finished方法。
    client.dispatcher().finished(this);
  }
}

7、dispatcher().finished(this)

作用:

调用dispatcher的finish方法,从当前队列移除任务,并继续调用promoteAndExecute方法,判断是否执行队列中的下个任务。

private <T> void finished(Deque<T> calls, T call) {
  Runnable idleCallback;
  synchronized (this) {
  //1、从对类中移除call
    if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
    idleCallback = this.idleCallback;
  }
  //2、调用promoteAndExecute,
  //3、isRunning = runningCallsCount() > 0;当前正在执行队列是否大于0
  boolean isRunning = promoteAndExecute();

  //3、判断回调idleCallback的run方法
  if (!isRunning && idleCallback != null) {
    idleCallback.run();
  }
}

8、RealCall的getResponseWithInterceptorChain()

作用:

1、将我们在OkHttpClient配置的interceptors和五大拦截器添加到集合中。

2、调用RealInterceptorChain的proceed方法,通过链式调用调用拦截器集合中的拦截器,获得response。最终返回给reallCall。

Response getResponseWithInterceptorChain() throws IOException {
  // Build a full stack of interceptors.
  List<Interceptor> interceptors = new ArrayList<>();
  //1、添加我们自定义的拦截器,在配置 OkHttpClient 时设置的 interceptors;
  interceptors.addAll(client.interceptors());
   // 2、负责失败重试以及重定向
  interceptors.add(new RetryAndFollowUpInterceptor(client));
   //3、请求时,对必要的Header进行一些添加,接收响应时,移除必要的Header
  interceptors.add(new BridgeInterceptor(client.cookieJar()));
    // 4、负责读取缓存直接返回、更新缓存
  interceptors.add(new CacheInterceptor(client.internalCache()));
      //5、负责和服务器建立连接
  interceptors.add(new ConnectInterceptor(client));
  if (!forWebSocket) {
    //6、配置OkHttpClient 时设置的 networkInterceptors
    interceptors.addAll(client.networkInterceptors());
  }
   //7、负责向服务器发送请求数据、从服务器读取响应数据
  interceptors.add(new CallServerInterceptor(forWebSocket));
  //这里会初始化RealInterceptorChain,传递为0,设置index为0。
  Interceptor.Chain chain = new RealInterceptorChain(interceptors, transmitter, null, 0,
    originalRequest, this, client.connectTimeoutMillis(),
    client.readTimeoutMillis(), client.writeTimeoutMillis());
 、、、
  try {
     // 8、使用责任链模式开启链式调用
    Response response = chain.proceed(originalRequest);
     、、、
  }
}

9、RealInterceptorChain的proceed方法

作用:

(1)获取拦截器集合,创建拦截器链RealInterceptorChain,然后通过链式依次调用拦截器。

(2)调用拦截器的intercept方法,之后会回调chain的proceed方法

(3)每调用一个拦截器都会返回response,拦截器集合调用完毕之后,会把response返回给

RealCall的getResponseWithInterceptorChain方法。

public Response proceed() {
 //1、index在RealInterceptorChain的构造函数初始化,刚开始为0
  if (index >= interceptors.size()) throw new AssertionError();
  calls++;
   、、、
  //这里进行了index + 1
  // Call the next interceptor in the chain.
  RealInterceptorChain next = new RealInterceptorChain(interceptors, transmitter, exchange,
      index + 1, request, call, connectTimeout, readTimeout, writeTimeout);
   //从interceptors获取拦截器,得到当前的拦截器
  Interceptor interceptor = interceptors.get(index);
   //调用拦截器的intercept方法,并把RealInterceptorChain传递到拦截器中,方便继续调用当前chain的proceed方法。
  Response response = interceptor.intercept(next);
  //把response返回上一个拦截器,最终会返回给RealCall。
  return response;
}

10、拦截器集合

拦截器逻辑总结:

  1. 在发起请求前对request进行处理
  2. 调用下一个拦截器,获取response
  3. 对response进行处理,返回给上一个拦截器

    1、我们自定义的DebugInterceptor

通过DebugInterceptor,我们可以实现设置本地json返回数据。在后端接口没有发布的时候,提前进行数据联调。

public class DebugInterceptor implements Interceptor {
    private final String DEBUG_URL;
    private final int DEBUG_RAW_ID;
    private Context mContext;
    public DebugInterceptor(String debug_url, int debug_raw_id,Context context) {
        DEBUG_URL = debug_url;
        DEBUG_RAW_ID = debug_raw_id;
        mContext=context;
    }
    private Response getResponse(Interceptor.Chain chain, String json) {
        return new Response.Builder()
                .code(200)
                .addHeader("Content-Type", "application/json")
                .body(ResponseBody.create(MediaType.parse("application/json"), json))
                .request(chain.request())
                .message("ok")
                .protocol(Protocol.HTTP_1_1)
                .build();
    }
    private Response debugResponse(Interceptor.Chain chain, @RawRes int rawId) {
        final String json = FileUtils.getRawFile(mContext,rawId);
        return getResponse(chain, json);
    }
    @Override
    public Response intercept(Interceptor.Chain chain) throws IOException {
        final String url = chain.request().url().toString();
        if (url.contains(DEBUG_URL)) {
            return debugResponse(chain, DEBUG_RAW_ID);
        }
        return chain.proceed(chain.request());
    }
}

 

2、RetryAndFollowUpInterceptor

作用:重试和重定向拦截器,负责网络请求失败,进行重试。进行重定向。

1、开启一个while (true) 循环

2、调用RealInterceptorChain.proceed进行网络请求,获取response

3、如果有异常,调用continue,终止下面的方法调用,在while (true) 循环中,继续调用2的方法。这里会有一个

4、如果没有异常,对response进行判断,然后return response,跳出while (true) 循环,把response返回给上一个拦截器

5、如果没有return response,这里有一个重试次数的判断,如果超过,会抛出异常。

源码:

@Override public Response intercept(Chain chain) throws IOException {
  //1、获取request
  Request request = chain.request();
   //2、类型强转为RealInterceptorChain
  RealInterceptorChain realChain = (RealInterceptorChain) chain;
  Transmitter transmitter = realChain.transmitter();
  int followUpCount = 0;
  Response priorResponse = null;
   //3、创建死循环
  while (true) {
  stream
   //4、创建一个strem留来携带request
    transmitter.prepareToConnect(request);
    、、、
    try {
    //5、把request和transmitter传递给下一个拦截器,并调用拦截器的intercept方法
      response = realChain.proceed(request, transmitter, null);

    } catch (Exception e) {
    、、、
    //如果有异常,继续下一次循环
      continue;
    } finally {
      // The network call threw an exception. Release any resources.
     //6、网络有异常,释放资源
       if (!success) {
        transmitter.exchangeDoneDueToException();
      }
    }
     //7、对response的responseCode返回码进行判断
    Request followUp = followUpRequest(response, route);
    在下面进行一些判断,如果正常,返回response。
、、、
   //8、这里会统计重试的次数,如果大于20次,抛出异常,终止循环。
    if (++followUpCount > MAX_FOLLOW_UPS) {
      throw new ProtocolException("Too many follow-up requests: " + followUpCount);
    }
、、、
  }
}

3、BridgeInterceptor

作用:桥接适配拦截器,设置请求内容长度、内容编码、cookie、gzip

1、负责将我们构建的request转化为能够进行网络请求的request,比如添加头部信息。

Content-Type、Content-Length、Transfer-Encoding、Host、Connection=”Keep-Alive”保持长连接,Accept-Encoding、Cookie、User-Agent

2、调用拦截器链的proceed方法,调用下一个拦截器的intercept方法,进行网络请求。

3、将服务器返回的response进行处理,变成我们可以使用的response。比如gzip压缩。

4、CacheInterceptor

作用:负责缓存管理,

1、根据request得到cache中缓存的response

2、当网络请求和缓存为空的时候,抛出504(网关超时)的异常。

3、如果网络请求为空,缓存不为空,直接返回缓存response。

4、调用拦截器链的proceed方法,调用下一个拦截器获取网络数据。

5、如果缓存不为空,对返回的networkResponse的返回码进行判断,如果code是304,那么直接返回缓存,并更新缓存。

6、如果cache为空,对数据进行缓存。

7、判断request,如果为空,将cache中对应的request缓存删除。

@Override public Response intercept(Chain chain) throws IOException {
    // 1、根据request得到cache中缓存的response
    Response cacheCandidate = cache != null
        ? cache.get(chain.request())
        : null;
    long now = System.currentTimeMillis();
    // 通过request通过一系列判断创建缓存策略。
    request判断缓存的策略,是否要使用了网络,缓存或两者都使用
    CacheStrategy strategy = new CacheStrategy.Factory(now, chain.request(),     cacheCandidate).get();
    Request networkRequest = strategy.networkRequest;
    Response cacheResponse = strategy.cacheResponse;
    if (cache != null) {
      cache.trackResponse(strategy);
    }
    if (cacheCandidate != null && cacheResponse == null) {
      closeQuietly(cacheCandidate.body()); // The cache   candidate wasn't applicable. Close it.
    }
    //当网络请求和缓存为空的时候,抛出504(网关超时)的异常。
    if (networkRequest == null && cacheResponse == null) {
      return new Response.Builder()
          .request(chain.request())
          .protocol(Protocol.HTTP_1_1)
          .code(504)
          .message("Unsatisfiable Request (only-if-cached)")
          .body(Util.EMPTY_RESPONSE)
          .sentRequestAtMillis(-1L)
          .receivedResponseAtMillis(System.currentTimeMillis())
          .build();
    }
    // 网络请求为空,直接返回response
    if (networkRequest == null) {
      return cacheResponse.newBuilder()
          .cacheResponse(stripBody(cacheResponse))
          .build();
    }
    Response networkResponse = null;
    try {
        // 调用下一个拦截器,决定从网络上来得到response
        networkResponse = chain.proceed(networkRequest);
    } finally {
        // If we're crashing on I/O or otherwise,   don't leak the cache body.
        if (networkResponse == null && cacheCandidate != null) {
          closeQuietly(cacheCandidate.body());
        }
    }
    // If we have a cache response too, then we're doing a conditional get.
    // 如果本地已经存在cacheResponse,那么让它和网络得到的networkResponse做比较,决定是否来更新缓存的cacheResponse
    if (cacheResponse != null) {
    //HTTP_NOT_MODIFIED表示304,表示从缓存中获取数据
        if (networkResponse.code() == HTTP_NOT_MODIFIED)   {
          Response response = cacheResponse.newBuilder()
                  .headers(combine(cacheResponse.headers(), networkResponse.headers()))
                  .sentRequestAtMillis(networkResponse.sentRequestAtMillis())
                  .receivedResponseAtMillis(networkResponse.receivedResponseAtMillis())
                  .cacheResponse(stripBody(cacheResponse))
                  .networkResponse(stripBody(networkResponse))
              .build();
          networkResponse.body().close();
          // Update the cache after combining headers but before stripping the
          // Content-Encoding header (as performed by initContentStream()).
          cache.trackConditionalCacheHit();
          cache.update(cacheResponse, response);
          return response;
        } else {
          closeQuietly(cacheResponse.body());
        }
    }
    Response response = networkResponse.newBuilder()
        .cacheResponse(stripBody(cacheResponse))
        .networkResponse(stripBody(networkResponse))
        .build();
    if (cache != null) {
      if (HttpHeaders.hasBody(response) && CacheStrategy.isCacheable(response,   networkRequest)) {
        // Offer this request to the cache.
        // 缓存未经缓存过的response
        CacheRequest cacheRequest = cache.put(response);
        return cacheWritingResponse(cacheRequest, response);
      }
      if (HttpMethod.invalidatesCache(networkRequest.method())) {
        try {
          cache.remove(networkRequest);
        } catch (IOException ignored) {
          // The cache cannot be written.
        }
      }
    }
    return response;
}

5、ConnectInterceptor

网络连接器作用:

1、获取从realChain传递的过来的Transmitter,这个Transmitter是在RetryAndFollowUpInterceptor创建的。

2、通过Transmitter创建exchange,他会携带request和response。在这里我们会获取网络链接,首先判断是否有合适的链接,如果没有我们连接池取,复用已有的链接。如果还是没有,我们会自己创建一个链接RealConnection。然后调用RealConnection的connect方法,进行TCP 和 TLS 握手,这里是难点。

3、调用realChain的proceed方法

@Override public Response intercept(Chain chain) throws IOException {
  RealInterceptorChain realChain = (RealInterceptorChain) chain;
  Request request = realChain.request();
  //1、在RetryAndFollowUpInterceptor我们会创建一个流,现在取出这个流,Transmitter
  Transmitter transmitter = realChain.transmitter();
、、、
//2、通过transmitter,我们创建一个exchange,他会携带request和response。
  Exchange exchange = transmitter.newExchange(chain, doExtensiveHealthChecks);
  //调用realChain的proceed方法
  return realChain.proceed(request, transmitter, exchange);
}
//现在重点到transmitter.newExchange方法,这个方法通过一些列判断最终会调用findHealthyConnection。首先开启一个while (true) ,在死循环中调用findConnection方法。
private RealConnection findConnection() throws IOException {
    、、、
  synchronized (connectionPool) {
    、、、
   //如果transmitter的connection不为空,我们将它赋值为result
    if (transmitter.connection != null) {
      // We had an already-allocated connection and it's good.
      result = transmitter.connection;
      releasedConnection = null;
    }
     //如果result为空,我们尝试从连接池中国取出一个链接
    if (result == null) {
      // Attempt to get a connection from the pool.
      if (connectionPool.transmitterAcquirePooledConnection(address, transmitter, null, false)) {
        foundPooledConnection = true;
        result = transmitter.connection;
      } 
    }
  }
  、、、
 //如果还是没有链接,那我们自己创建一个链接
 result = new RealConnection(connectionPool, selectedRoute);

  //进行 TCP 和 TLS 握手,这是一个耗时操作。这里是重点和难点
  result.connect();
  、、、
  // 将该连接放进连接池中,连接池的实现是队列+线程池。
  connectionPool.put(result);
  return result;
}

6、CallServerInterceptor

作用:

写入我们的请求头和请求体,然后通过Okio向服务器发出真正的网络请求,读取服务器返回的数据并返回。Okio是另外一个库。真正的IO操作是在Okio进行实现的。

@Override public Response intercept(Chain chain) throws IOException {
  RealInterceptorChain realChain = (RealInterceptorChain) chain;
  Exchange exchange = realChain.exchange();
  Request request = realChain.request();
  //通过exchange写入我们的请求头
  exchange.writeRequestHeaders(request);
  、、
  //经过一系列判断,如果是正常的网络请求,会通过Okio进行网络请求
        BufferedSink bufferedRequestBody = Okio.buffer(
            exchange.createRequestBody(request, true));
     //写入我们的请求body       
        request.body().writeTo(bufferedRequestBody);
      } 
  //停止写入我们的请求信息
  if (request.body() == null || !request.body().isDuplex()) {
    exchange.finishRequest();
  }
//读取我们的response头部
  if (responseBuilder == null) {
    responseBuilder = exchange.readResponseHeaders(false);
  }
//读取我们的response
  Response response = responseBuilder
      .request(request)
      .handshake(exchange.connection().handshake())
      .sentRequestAtMillis(sentRequestMillis)
      .receivedResponseAtMillis(System.currentTimeMillis())
      .build();

  exchange.responseHeadersEnd(response);
//接下来会对response的code做一些判断
  return response;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值