框架【库】Android收藏集芳草集

手把手讲解 OkHttp硬核知识点(2)

2019-08-15  本文已影响17人  波澜步惊

前言

手把手讲解系列文章,是我写给各位看官,也是写给我自己的。
文章可能过分详细,但是这是为了帮助到尽量多的人,毕竟工作5,6年,不能老吸血,也到了回馈开源的时候.
这个系列的文章:
1、用通俗易懂的讲解方式,讲解一门技术的实用价值
2、详细书写源码的追踪,源码截图,绘制类的结构图,尽量详细地解释原理的探索过程
3、提供Github 的 可运行的Demo工程,但是我所提供代码,更多是提供思路,抛砖引玉,请酌情cv
4、集合整理原理探索过程中的一些坑,或者demo的运行过程中的注意事项
5、用gif图,最直观地展示demo运行效果

如果觉得细节太细,直接跳过看结论即可。
本人能力有限,如若发现描述不当之处,欢迎留言批评指正。

学到老活到老,路漫漫其修远兮。与众君共勉 !


引子

OkHttp 知名第三方网络框架SDK,使用简单,性能优秀,但是内核并不简单,此系列文章,专挑硬核知识点详细讲解. 何为硬核,就是要想深入研究,你绝对绕不过去的知识点

本文接上一篇文章: https://www.jianshu.com/p/dc06a54e920a
详细讲解 OKHttp的核心内容,拦截器。不过拦截器众多,有系统自带的,也有我们可以自己去自定义的。

image.png

这是网络请求执行的核心方法的起点,这里涉及了众多拦截器,

正文大纲

系统自带拦截器

1 重试与重定向拦截器 RetryAndFollowUpInterceptor
2 桥接拦截器 BridgeInterceptor
3 缓存拦截器 CacheInterceptor
4 连接拦截器 ConnectInterceptor
5 服务调用拦截器 CallServerInterceptor

可自定义的拦截器

  • 继承Intercetor
  • 继承NetworkInterceptor

正文

在详解拦截器之前,有必要先将 RealCallgetResponseWithInterceptorChain() 方法最后两行展开说明:

Interceptor.Chain chain = new RealInterceptorChain( interceptors, null, null, null, 0, originalRequest);
return chain.proceed(originalRequest);

这里最终返回 一个Response,进入chain.proceed方法,最终索引到 RealInterceptorChainproceed方法:

image.png
之后,我们追踪这个interceptor.intercept(next); ,发现是一个接口,找到实现类,有多个,进入其中的RetryAndFollowUpInterceptor,发现:
image.png
它这里又执行了 chain.proceed,于是又回到了RealInterceptorChain.proceed()方法,但是此时,刚才链条中的拦截器已经不再是原来的拦截器了,而是变成了第二个,因为每一次都index+1了(这里比较绕,类似递归,需要反复仔细体会),依次类推,直到所有拦截器的intercept方法都执行完毕,直到链条中没有拦截器。就返回最后的Response

这一段是okhttp责任链模式的核心,应该好理解。

系统自带拦截器

1. 重试与重定向拦截器 RetryAndFollowUpInterceptor

先说结论吧:

顾名思义,retry 重试, FollowUp 重定向 。这个拦截器处在所有拦截器的第一个,它是用来判定要不要对当前请求进行重试和重定向的,那么我们应该关心的是:什么时候重试什么时候重定向

先来关注一下RetryAndFollowUpInterceptor的核心方法 interceptor() :

@Override public Response intercept(Chain chain) throws IOException {
    ...省略
    while (true) {
      ...省略
      try {
        response = ((RealInterceptorChain) chain).proceed(request, streamAllocation, null, null);
        releaseConnection = false;
      } catch (RouteException e) {
        // The attempt to connect via a route failed. The request will not have been sent.
        if (!recover(e.getLastConnectException(), false, request)) {
          throw e.getLastConnectException();
        }
        releaseConnection = false;
        continue;
      } catch (IOException e) {
        // An attempt to communicate with a server failed. The request may have been sent.
        boolean requestSendStarted = !(e instanceof ConnectionShutdownException);
        if (!recover(e, requestSendStarted, request)) throw e;
        releaseConnection = false;
        continue;
      }
      ...省略
      if (followUp == null) {
        if (!forWebSocket) {
          streamAllocation.release();
        }
        return response;
      }
      ...省略

    }
  }

上面的代码中,我只保留了关键部分。其中有两个continue,一个return.

当请求到达了这个拦截器,它会进入一个while(true)循环,当发生了RouteException 异常(这是由于请求尚未发出去,路由异常,连接未成功),就会去判断recover方法的返回值,根据返回值决定要不要continue.
当发生IOException(请求已经发出去,但是和服务器通信失败了)之后,同样去判断recover方法的返回值,根据返回值决定要不要continue.
recover()方法内部:

如果这两个continue都没有执行,就有可能走到最后的return response结束本次请求.


2. 桥接拦截器 BridgeInterceptor


3. 缓存拦截器 CacheInterceptor


4. 连接拦截器 ConnectInterceptor


5. 服务调用拦截器 CallServerInterceptor


可自定义的拦截器

继承Intercetor


继承NetworkInterceptor


结语


上一篇下一篇

猜你喜欢

热点阅读