文档章节

OkHttp的Interceptor原理分析

林泳坛
 林泳坛
发布于 2016/03/03 13:48
字数 841
阅读 653
收藏 1

OkHttp的Interceptor原理分析

标签(空格分隔): Java OkHttp Interceptor Chain


样例

OkHttpClient mClient = new OkHttpClient();
CookieManager cookieManager = new CookieManager(new PersistentCookieStore(BaseApplication.instance()), CookiePolicy.ACCEPT_ALL);
mClient.setCookieHandler(cookieManager);
mClient.interceptors().add(chain -> {
    Request originReq = chain.request();
    HttpUrl httpUrl = originReq.httpUrl().newBuilder().addQueryParameter("auth_token", BaseApplication.instance().getToken()).build();
    Request.Builder reqBuilder = originReq.newBuilder();
    reqBuilder.header("mobile_platform", "android").url(httpUrl);
    Request req = reqBuilder.build();
    Response resp = chain.proceed(req);
    if (Settings.isDebug) {
    }
    return resp;
});
if (Settings.isDebug) {
    HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
    logging.setLevel(HttpLoggingInterceptor.Level.BODY);
    mClient.interceptors().add(logging);
}

上面代码中,我已经向mClient中添加了两个拦截器。第一个用于给原来的请求添加一个auth_token查询参数,第二个用于在请求前后把请求的内容和响应的内容打出来到控制台中。

入口

首先,得把OkHttp的源码git下来,然后找到OkHttpClient类,再找到其中的newCall(request)方法。好,故事从这里开始。代码如下,

  /**
   * Prepares the {@code request} to be executed at some point in the future.
   */
  public Call newCall(Request request) {
    return new Call(this, request);
  }

很简单,就是直接新建一个Call对象而已,所以关键不是这里,而是Call类。我们拿到Call对象之后一般是调用enqueue方法或者execute方法。我们就拿比较简单的execute方法来做切入点。对应的代码如下,

  public Response execute() throws IOException {
  
    ··· 这里省略了若干行代码
    
    try {
      client.getDispatcher().executed(this);
      Response result = getResponseWithInterceptorChain(false);
      if (result == null) throw new IOException("Canceled");
      return result;
    } finally {
      client.getDispatcher().finished(this);
    }
  }

上面代码中,关键在于getResponseWithInterceptorChain方法。最后我们的结果也就是从这个方法中产生的,代码如下,

  private Response getResponseWithInterceptorChain(boolean forWebSocket) throws IOException {
    Interceptor.Chain chain = new ApplicationInterceptorChain(0, originalRequest, forWebSocket);
    return chain.proceed(originalRequest);
  }

  class ApplicationInterceptorChain implements Interceptor.Chain {
    private final int index;
    private final Request request;
    private final boolean forWebSocket;

    ApplicationInterceptorChain(int index, Request request, boolean forWebSocket) {
      this.index = index;
      this.request = request;
      this.forWebSocket = forWebSocket;
    }

    ··· 这里省略了若干行代码

    @Override public Response proceed(Request request) throws IOException {
      // If there's another interceptor in the chain, call that.
      if (index < client.interceptors().size()) {
        Interceptor.Chain chain = new ApplicationInterceptorChain(index + 1, request, forWebSocket);
        Interceptor interceptor = client.interceptors().get(index);
        Response interceptedResponse = interceptor.intercept(chain);

        ··· 这里省略了若干行代码

        return interceptedResponse;
      }

      // No more interceptors. Do HTTP.
      return getResponse(request, forWebSocket);
    }
  }

从上面代码中,我们看到有一个ApplicationInterceptorChain这个种东西参与其中。这个东西是责任链设计模式的关键——链,它把多个处理器(对应这里的Interceptor)串联在一起,并且请求会在条链上传递下去,直到找到真正有责任处理这个请求的处理器(即这里的Interceptor)。上面代码中,我们可以看出,处理请求的责任落在了最后一个处理器上。

代码是最好的文档,我们看它的类定义。它实现了Chain接口,就是我们向OkHttpClient中添加Interceptor时接收到的参数。它的作用是记录当前Intercepter的索引(index)和Request对象,并且请求index对应的拦截器获取结果,并且把下链条的下一截作为参数传给拦截器。拦截器收到chain参数后,最终还是要调用chain的proceed方法。所以,这里就是一个递归过程,一直到最后一个拦截器,才真正的进入到OkHttp的网络请求核心获取数据。获取到数据之后,Response就会在拦截器中逆向传递。

声名

By 啪嗒科技 AtanL(atanl@padakeji.com)

©啪嗒科技版本所有,没有经作者允许,只能发表于padakeji.com相关域名下。

© 著作权归作者所有

共有 人打赏支持
下一篇: Fragment填坑记
林泳坛
粉丝 3
博文 18
码字总数 13321
作品 0
广州
程序员
私信 提问
OkHttp 3.x 源码解析之Interceptor 拦截器

Tamic / 开发者技术前线 OkHttp拦截器原理解析 在进行下文前,先说明一点,本文面向的是对Okhttp有一定基础的读者,Okhttp基础使用请阅读我的其他OKhttp+Retrofit+RxJava基础用法的文章: OK...

10/28
0
0
Android面试的那些答不上来的问题(一)--- OkHttp的拦截器你到底了解多少(上)

前言 前段时间面试了很多家公司(坐标成都,大大小小加起来得20家吧),有时候有些事做多了,你就会发现它的一些窍门或者规律,面试这件事当然也不例外。其实很多公司问到的问题都大同小异,...

SillyMonkey
05/10
0
0
Android面试有迹可循(一)OkHttp3.9拦截器原理与区别

接上回 传送门 上回我们讲到,OkHttp的请求过程中有个非常重要的东西-“拦截器”,而且拦截器又分为interceptors和networkInterceptors两种,那它们具体有何区别呢?又要怎么来使用?现在来一...

SillyMonkey
05/19
0
0
OkHttp优雅的实现下载监听

OkHttp优雅的实现下载监听 (ps:很久很久没有发什么博文了,打字都要锈了,请允许我在这里水一波~~) 我们都知道okhttp的运转原理,通过interceptor拦截器一层一层嵌套执行。要实现下载监听,...

北纬34点8度
08/21
0
0
Android技能树 — 网络小结之 OkHttp超超超超超超超详细解析

前言: 本文也做了一次标题党,哈哈,其实写的还是很水,各位原谅我O(∩_∩)O。 介于自己的网络方面知识烂的一塌糊涂,所以准备写相关网络的文章,但是考虑全部写在一篇太长了,所以分开写,...

青蛙要fly
11/13
0
0

没有更多内容

加载失败,请刷新页面

加载更多

多线程的实现方式

多线程是指 一个程序运行时,产生或使用了不止一个线程。 线程的生命周期是怎么样的,下面这张图我们可以看出些端倪: 这章我们主要讨论多线程实现的方式,基础知识部分我们可以下来再恶补。...

搬砖大侠
6分钟前
0
0
新人千万不要在 Windows 上使用 Ruby on Rails

标题:新人千万不要在 Windows 上使用 Ruby on Rails 副标题:鼓励新人在 Linux 和 Mac 上使用 Ruby on Rails ! 原则:要走寻常路,不要学美特斯邦伟! "在 Windows上 使用 Ruby on Rails "是...

Jason909
14分钟前
0
0
day177-2018-12-14-英语流利阅读-待学习

艾滋病的治愈方法是否触手可及? Daniel 2018-12-14 1.今日导读 几十年来,艾滋病一直是世界上最难对付的“超级绝症”之一,从人类历史上第一次诊断出艾滋病病例的 20 世纪 80 年代早期到 20...

飞鱼说编程
39分钟前
7
0
java 合成两张图片或图片与二维码

java中偶尔会出现需要将一张小图片嵌入大图中或带二维码的海报图片,那么本文就是奔着这个目的来的,直接上腊肉! zxing是生成1D和2D条形或二维码的工具类库,java图形库Graphics2D进行图片的...

貔貅叔
44分钟前
4
0
80后阿里P10,“关老板”如何带着MaxCompute一路升级?

我是个幸运的人。虽然幸运不能被复制,但是眼光和努力可以。 关涛/关老板,80后的阿里P10,阿里巴巴通用计算平台负责人,阿里巴巴计算平台研究员。12年职场人生,微软和阿里的选择。 关涛的花...

阿里云官方博客
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部