Okhttp3 拦截器链过程浅析(四)

拦截器:Okhttp中提供的一种强大的机制,可以实现网络监听、请求/响应重写、请求失败重试等功能的实现(拦截器不区分异步/同步)

Okhttp不管是异步/同步,在RealCall.java中都会执行Response result = getResponseWithInterceptorChain();

  • 同步
RealCall.java

@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();//执行该方法
      .....省略无用代码
  }

  • 异步
RealCall.java

@Override public void enqueue(Callback responseCallback) {
    ...省略无用代码
    client.dispatcher().enqueue(new AsyncCall(responseCallback));//跟到AsyncCall中
  }

==============================分割线=========================

AsyncCall.execute();

@Override protected void execute() {
      boolean signalledCallback = false;
      try {
        Response response = getResponseWithInterceptorChain();//异步也是执行该方法
        ....省略无用代码
    }

接下来看一下getResponseWithInterceptorChain()具体做了什么操作,源码如下:

//方法字面意思:得到一个具有拦截器链的响应
Response getResponseWithInterceptorChain() throws IOException {
    // Build a full stack of interceptors.
    List 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));

    //拦截器链
    Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
        originalRequest, this, eventListener, client.connectTimeoutMillis(),
        client.readTimeoutMillis(), client.writeTimeoutMillis());

    //执行RealInterceptorChain.proceed();方法,下面将具体分析
    return chain.proceed(originalRequest);
  }

上面的getResponseWithInterceptorChain()是通过RealInterceptorChain.proceed();方法得到一个拦截器链,下面具体看一下proceed()方法:

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.
    // 在这里,得到了 next 下一个链,构造函数中将 index+1 
    RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
        connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
        writeTimeout);
    //interceptors 就是从构造函数中,得到的List
    //也就是在RealCall.getResponseWithInterceptorChain();中添加的所有的拦截器
    Interceptor interceptor = interceptors.get(index);
    //在这里,执行拦截器的intercept();方法
    //在具体拦截器的intercept()方法中,又会调用next chain的proceed();方法
    //构成了一个链
    Response response = interceptor.intercept(next);

    ....省略部分代码

    return response;
  }

proceed()方法执行过程大概是:
在内部将index+1,得到下一个RealInterceptorChain,通过具体的拦截器的intercept()方法,继续执行下一个链的proceed();方法,依次直到最后一个拦截器,从而形成一个链(有点类似于递归,依次往内部请求,结果从最内部一层一层传到最外层)。

你可能感兴趣的:(Okhttp3 拦截器链过程浅析(四))