# Okhttp解析—Interceptor详解

本文详细介绍了OkHttp中的Interceptor机制,包括InterceptorChain的工作原理,以及RetryAndFollowUpInterceptor、BridgeInterceptor、CacheInterceptor、ConnectInterceptor和CallServerInterceptor五个内置Interceptor的详细功能。Interceptor链式调用的过程和每个Interceptor在请求和响应过程中的作用被逐一剖析,帮助理解OkHttp如何处理网络请求和响应。
摘要由CSDN通过智能技术生成

Okhttp解析—Interceptor详解

Interceptor可以说是okhttp的精髓之一,Okhttp重写请求/响应、重试、缓存响应等操作,基本都是在各个Interceptor中完成的,上篇文章分析Okhttp运行流程时只是简单带过,那么这篇文章就来详细分析下Interceptor以及拦截器链机制。

一、Interceptor以及InterceptorChain

/**
 * Observes, modifies, and potentially short-circuits requests going out and the corresponding
 * responses coming back in. Typically interceptors add, remove, or transform headers on the request
 * or response.
 */
public interface Interceptor {
  Response intercept(Chain chain) throws IOException;

  interface Chain {
    Request request();

    Response proceed(Request request) throws IOException;

    /**
     * Returns the connection the request will be executed on. This is only available in the chains
     * of network interceptors; for application interceptors this is always null.
     */
    @Nullable Connection connection();

    Call call();

    int connectTimeoutMillis();

    Chain withConnectTimeout(int timeout, TimeUnit unit);

    int readTimeoutMillis();

    Chain withReadTimeout(int timeout, TimeUnit unit);

    int writeTimeoutMillis();

    Chain withWriteTimeout(int timeout, TimeUnit unit);
  }
}

Interceptor最主要的就是其intercept()函数,InterceptorChain则是Interceptor一个内部类,它的主要作用就是链式有序调用Interceptor。

Okhttp内置了5种Interceptor它们分别是RetryAndFollowUpInterceptor
、BridgeInterceptor、CacheInterceptor、ConnectInterceptor
、CallServerInterceptor。正是这5种Interceptor完成了重写、重试、缓存、请求等操作,接下来我们来逐一分析它们的作用。

二、Interceptor链式调用

拦截器调用的入口是在ReallCall的getResponseWithInterceptorChain()函数中。

Response getResponseWithInterceptorChain() throws IOException {
    // Build a full stack of interceptors.
    List<Interceptor> interceptors = new ArrayList<>();
    interceptors.addAll(client.interceptors());
    interceptors.add(new RetryAndFollowUpInterceptor(client));
    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, transmitter, null, 0,
        originalRequest, this, client.connectTimeoutMillis(),
        client.readTimeoutMillis(), client.writeTimeoutMillis());//1

    boolean calledNoMoreExchanges = false;
    try {
      Response response = chain.proceed(originalRequest);//2
      if (transmitter.isCanceled()) {
        closeQuietly(response);
        throw new IOException("Canceled");
      }
      return response;
    } catch (IOException e) {
      calledNoMoreExchanges = true;
      throw transmitter.noMoreExchanges(e);
    } finally {
      if (!calledNoMoreExchanges) {
        transmitter.noMoreExchanges(null);
      }
    }
  }

我们看到该函数一开始就构造了一个List然后向里边添加所有的Interceptor,包括我们自定义的Application Interceptor、系统预置的Interceptor、自定义的Network Interceptor等。
然后在注释1处构造RealInterceptorChain实例并传入刚刚的interceptor list还有就是我们看到第四个参数此处传入的是0。该参数表示接下来要调用interceptor list中哪个interceptor。
最后在注释2处调用chain.proceed()并传入原始请求。

@Override public Response proceed(Request request) throws IOException {
  return proceed(request, transmitter, exchange);
}

public Response proceed(Request request, Transmitter transmitter, @Nullable Exchange exchange)
    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.exchange != null && !this.exchange.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.exchange != 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, transmitter, exchange,
      index + 1, request, call, connectTimeout, readTimeout, writeTimeout);//1
  Interceptor interceptor = interceptors.get(index);//2
  Response response = interceptor.intercept(next);//3

  // Confirm that the next interceptor made its required call to chain.proceed().
  if (exchange != 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;
}

proceed函数我们主要关注3个注释处的操作。
在注释1处构造RealInterceptorChain,其中参数4此时变为index+1,index就是之前在getResponseWithInterceptorChain中构造RealInterceptorChain时传入的值。

注释2处通过index从Interceptor list中取出对应的Interceptor。
注释3处调用Interceptor的intercept()方法,参数传入注释1处构造的RealInterceptorChain。因为Interceptor的操作都是在intercept()函数中完成的,所以该操作完成了当前Interceptor的调用。同时在每个Interceptor的intercept()函数中都会调用next.proceed()这样就开启了下一个Interceptor调用,如此反复最终像链条一样依次调用Interceptor list中所有的Interceptor。

三、详解各个Interceptor

上边我们分析了Interceptor是按顺序调用的,这里的顺序指的是添加到Intercept

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值