(Android) OkHttp3.10 源码学习笔记 5 拦截器链分析

接上面的分析,在获取请求response的时候,都调用了如下代码

 Response response = 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));

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

    return chain.proceed(originalRequest);
  }    

上面的代码可以看到,首先添加了client.intercepors(),它们就是application 拦截器,然后添加了上篇文章介绍的五种内部拦截器,最后又添加了network拦截器

再看下面的代码

Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
        originalRequest, this, eventListener, client.connectTimeoutMillis(),
        client.readTimeoutMillis(), client.writeTimeoutMillis())

创建了RealInterceptorChain这个对象,将前面创建好的拦截器list传入,这样就完成了第一步。然后调用了chain的proceed()方法

@Override public Response proceed(Request request) throws IOException {
    return proceed(request, streamAllocation, httpCodec, connection);
  }

最终调用了四个参数的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.
    RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
        connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
        writeTimeout);
    Interceptor interceptor = interceptors.get(index);
    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;
  }

这个方法比较长,我们挑重点看

 // Call the next interceptor in the chain.
    RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
        connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
        writeTimeout);
    Interceptor interceptor = interceptors.get(index);
    Response response = interceptor.intercept(next);

上面这段代码也创建了一个拦截器链,这和刚才创建的区别在于他传入的参数是index+1,就传入了下一个拦截器,这样就把我们的整个拦截器构造成了一个链条,设计很巧妙喔。第三块获取response的代码,传入的是刚才构造的next拦截器链。

总结一下

1.创建一系列拦截器,放入一个拦截器list当中

2.创建一个拦截器链对象,并执行拦截器链的proceed方法,这里注意,执行的是下一个拦截器的intercept方法。

这里我们看一下intercept方法,这里执行的是chain的proceed方法,这样就印证了我们上面的说法,整个拦截器链完整的交替执行。

  response = realChain.proceed(request, streamAllocation, null, null);
        releaseConnection = false;

这里,可以把OkHttp的网络请求看成一个个拦截器的执行他的intercept方法的过程,这样应该比较好理解了。

再次总结一下

1.在发起请求前对Request进行处理

2.调用下一个拦截器,获取response

3.对response处理,返回给上一个拦截器


猜你喜欢

转载自blog.csdn.net/zhouy1989/article/details/80560704