一起来学习Android开源框架&简单分析OKHttp拦截器

这是我参与8月更文挑战的第4天,活动详情查看:8月更文挑战

简单回顾下同步/异步

  • 同步请求就是执行请求的阻塞式方式,直到HTTP响应返回才会停止阻塞
  • 异步请求就类似于非阻塞式的请求,它的执行结果一般都是通过接口回调的方式来告知调用者

拦截器简介

  1. 在官网给出的拦截器的解释是这样的,它是OkHttp提供一种强大机制,可以实现网络监听,请求以及响应重写,请求失败重试等等功能

但是这里我们需要注意的是,这里的拦截器是不区分同步/异步的;那么意思很明朗了,无论是同步还是异步我们都会使用到拦截器功能来进行实际的网络请求响应

  1. 可以看下面这张图,这是官网提供的

interceptors@2x.png

这里表明的是有两种拦截器,一种是Application应用程序拦截器,第二种是Network网络拦截器,而我们所要关心的是中间这个OkHttp Core,这就是okhttp框架给我们提供的系统内部的拦截器,当发送一个请求,会通过拦截器的链来执行请求

  1. 下面我们简单看下它系统内部所提供的五种拦截器

拦截器链.png

  • 第一个RetryAndFollowUpInterceptor是重试和失败重定向拦截器,主要做了初始化工作,创建streamAllocation对象

  • 接着BridgeInterceptor是桥接和适配拦截器,CacheInterceptor是缓存拦截器,他们的职责主要是用来补充用户创建请求当中缺少的一些必须的http请求头和处理缓存的功能

  • 接下来是两个比较重要的拦截器ConntectInterceptCallServerIntercept,这其实是网络交互的关键;其中CallServerIntercept是将我们的http请求写进网络的IO流当中,并且会从网络IO流读取服务端返回给我们客户端的数据,ConnectIntercept连接拦截器建立可用的连接,可以说它是CallServerIntercept的基础

拦截器源码分析

拦截器链

  1. 首先我们可以看下**getResponseWithInterceptorChain()**方法,它返回的是我们的响应结果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, this, eventListener, client.connectTimeoutMillis(),
        client.readTimeoutMillis(), client.writeTimeoutMillis());

    return chain.proceed(originalRequest);
  }
复制代码

其实这个方法就是依次执行不同的拦截器构成拦截器链(在拦截器中链用的比较频繁),它创建了集合interceptors用来添加各种拦截器,然后依次将上述五种拦截器依次添加到该集合中传入到构造函数中,构成了拦截器链

  1. 接下来我们来看下它的processd()方法,以下是它的核心实现代码
 // 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");
    }
复制代码

这里创建了拦截器链RealInterceptorChain,但是这个和之前的getResponseWithInterceptorChain()有明显区别,传入的参数是index+1,这样做的意义在于只能从下一个拦截器开始访问,而不能从当前拦截器开始访问,也就构成了一个链,这也是设计巧妙的地方;接下来要执行索引为index的interceptor方法,然后将刚才所获得的索引为next的拦截器传入进来,这样就把所有的拦截器构成了一个完整的链条

简单来说,该方法主要做了如下操作

  • 创建一系列拦截器和拦截器集合,将这些拦截器都放到这个集合当中
  • 创建一个拦截器链RealInterceptorChain,然后在拦截器链中执行它的processd()方法,其中在processd()中执行拦截器的构造方法,通过下标获得此次intercetpor,
  • 然后每次调用它的interceptor方法返回个Response,并且再次执行下一个拦截器的proceed方法,这样就形成了链式调用,构成了一个完整的拦截器链返回

拦截器总结

上面表述中,其实可以这么理解,把一个Okhttp的网络请求,看作是一个一个拦截器执行它的interceptor方法的过程

一个拦截器的interceptor方法有以下执行步骤

  • 在发起请求前对request进行处理(包括头部等等)
  • 调用下一个拦截器(拦截器链的概念),获取response
  • 对response进行响应处理,返回给上一个拦截器

尾言

以上就是整体拦截器的核心逻辑以及总结,接下来我会一个一个分析系统内部给出的拦截器,包括它的源码解析以及具体作用,欢迎各位和我一起学习,继续远航

未完待续

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享