android

okhttp源码解析--拦截器

2019-02-12  本文已影响37人  二妹是只猫
Okhttpclient流程图.png

拦截器的工作原理

okhttp中拦截器是一个重要的概念,而拦截器中最重要的就是的概念之后,会以这点为核心作出解析。okhttp的日常使用中我们经常都需要对拦截器进行一些重写操作,来满足我们在项目中的需求。常用的interceptornetworkInterceptor,但这里我们暂时不去了解它,在RealCall的execute()中执行了这段代码:

Response response = getResponseWithInterceptorChain();

在请求中通过getResponseWithInterceptorChain拦截器链最终得到返回Response,下面就一步一步的来看看我们是怎么通过拦截器最终获得的这个response

  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);
    return chain.proceed(originalRequest);
  }
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);
    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");
    }

    return response;
  }

在proceed中代码较多最主要的将它提出来:

    if (index >= interceptors.size()) throw new AssertionError();
  // Call the next interceptor in the chain.
    RealInterceptorChain next = new RealInterceptorChain(
        interceptors, streamAllocation, httpCodec, connection, index + 1, request);
    Interceptor interceptor = interceptors.get(index);
    Response response = interceptor.intercept(next);
// Confirm that the intercepted response isn't null.
    if (response == null) {
      throw new NullPointerException("interceptor " + interceptor + " returned null");
    }
    return response;
public interface Interceptor {
  Response intercept(Chain chain) throws IOException;

  interface Chain {
    Request request();

    Response proceed(Request request) throws IOException;

    Connection connection();
  }
}

就这样拦截器实现了链式调用,使我们一直往下调用拦截器链并通过当前拦截器interceptor.intercept(next)获得response返回给上一个拦截器。这样我们就把所有拦截器都执行完毕,这也是okhttp拦截器的核心逻辑,也是我们如何一步一步获取到接口的返回i

response = ((RealInterceptorChain) chain).proceed(request, streamAllocation, null, null);

这里是 RetryAndFollowUpInterceptor的intercept方法中一行代码补充我们上面所得到的结论

总结

关于okhttp内部使用的拦截器在okhttp源码解析--五种内部拦截器有所介绍。

上一篇 下一篇

猜你喜欢

热点阅读