OkHttp原理第二篇—OkHttp的责任链模式

作者简介:00后,22年刚刚毕业,一枚在鹅厂搬砖的程序员。

前置任务:学习此篇文章之前读者可以自行阅读上一篇文章OkHttp第一篇—使用与分发机制。此篇文章需要读者了解责任链模式,如果不太了解可以看笔者的这篇文章设计模式之责任链模式

学习目标:验证OkHttp的责任链模式,并分析其运行原理。

创作初衷:学习OkHttp的原理,阅读Kotlin框架源码,提高自己对Kotlin代码的阅读能力。为了读代码而读代码,笔者知道这是不对的,但作为应届生,提高阅读源码的能力笔者认为还是很重要的。


OkHttp第二篇-OkHttp的责任链模式

OkHttp Response的返回整体流程属于责任链模式,本篇文章重点分析其中的责任链模式

先说结论:OkHttp中有一个链条类,以及许多节点类,节点可以放在链条上,将需要发送的Request交给链条,启动链条,首节点就可以对Request进行加工并继续向下传递,最后一个节点将请求发出,当最后一个节点收到Response后,逐步向上传递,最终回到首节点。

流程如下图:

黑线代表Request的流向,红线代表Response的流向,在流向的过程中上游可以对下游的Request或Response进行加工处理

OkHttp原理第一篇—使用与分发机制中我们得出结论,无论异步请求还是同步请求Response都是调用RealCall中的 getResponseWithInterceptorChain()方法返回的,因此我们在从方法开始分析。

RealCall#getResponseWithInterceptorChain

@Throws(IOException::class)
internal fun getResponseWithInterceptorChain(): Response {
    // Build a full stack of interceptors.
    //初始化拦截器数组
    val interceptors = mutableListOf<Interceptor>()
    interceptors += client.interceptors //用户自定义的节点,可在构建Client时加入自己的节点
    interceptors += RetryAndFollowUpInterceptor(client)
    interceptors += BridgeInterceptor(client.cookieJar)
    interceptors += CacheInterceptor(client.cache)
    interceptors += ConnectInterceptor
	//是否属于webSocket协议链接,若是则添加networkInterceptors
    if (!forWebSocket) {
        interceptors += client.networkInterceptors
    }
    interceptors += CallServerInterceptor(forWebSocket)
	
    //创建Chain链条
    val chain = RealInterceptorChain(
        call = this,										//当前请求的Call(Request的载体)
        interceptors = interceptors,						//节点数组
        index = 0,											//目前需要执行的节点下标
        exchange = null,	
        request = originalRequest,							//原先的请求,后续会对请求进行再次封装
        connectTimeoutMillis = client.connectTimeoutMillis, //超时时间
        readTimeoutMillis = client.readTimeoutMillis,
        writeTimeoutMillis = client.writeTimeoutMillis
    )
	...

    //链条执行,下面分析
    val response = chain.proceed(originalRequest)
    
	...
    return response
    
    ...

}

HTTP请求分析,去掉自定义节点,此时链条会存在5个节点(在OkHttp中节点叫做拦截器,下文中全部使用拦截器):

  1. RetryAndFollowUpInterceptor 重试与重定向拦截器,主要处理错误信息进行重试和重定向操作
  2. BridgeInterceptor 桥接拦截器,对HTTP请求头进行封装,并处理请求体的压缩
  3. CacheInterceptor 缓存拦截器, 处理HTTP的缓存操作
  4. ConnectInterceptor 连接拦截器,建立Socket连接
  5. CallServerInterceptor请求拦截器,对Socket的输入流和输出流进行操作,真正的请求发起者和相应接收者

上述拦截器的作用还无需理解,此小节重点分析OkHttp的责任链的执行过程。

@Throws(IOException::class)
override fun proceed(request: Request): Response {
    ...
    //创建一个新的链条,使当前下标加1,看下1中分析copy函数
    val next = copy(index = index + 1, request = request)
    val interceptor = interceptors[index]
    @Suppress("USELESS_ELVIS")
    //执行节点的处理,将下标加1的next链条交给当前拦截器,看下2,分析当前节点如何启动下一个节点
    val response = interceptor.intercept(next) ?: throw NullPointerException(
        "interceptor $interceptor returned null")
	...

    return response
}

1.RealInterceptorChain#copy

返回一个新的RealInterceptorChain

internal fun copy(
  index: Int = this.index,
  exchange: Exchange? = this.exchange,
  request: Request = this.request,
  connectTimeoutMillis: Int = this.connectTimeoutMillis,
  readTimeoutMillis: Int = this.readTimeoutMillis,
  writeTimeoutMillis: Int = this.writeTimeoutMillis
) = RealInterceptorChain(call, interceptors, index, exchange, request, connectTimeoutMillis,
    readTimeoutMillis, writeTimeoutMillis)

2.RetryAndFollowUpInterceptor,BridgeInterceptor,CacheInterceptor,ConnectInterceptor#intercept

override fun intercept(chain: Interceptor.Chain): Response {
    val realChain = chain as RealInterceptorChain
    var request = chain.request
    //对Request进行处理
  	...
    //进行递归,回到上的proceed()方法,此时index下标已经+1,执行下一个拦截器的处理
    response = realChain.proceed(request)
    //对response进行处理
    ...
    return response
         
}

前四个拦截器的处理方法类似,第五个拦截器会有所不同,其Response会直接通过网路返回的数据进行构建,不会再往下传递。

总结:整理一下上述流程,当调用getResponseWithInterceptorChain()方法后,初始化拦截器和链条,并为链条添加5个节点,后续调用链条的proceed()方法,proceed()会去创建一个新链条,并使下标加1,再执行当前链条的下标位置的拦截器的intercept()方法,并将刚才创建的链条当成参数传入intercept()方法,在拦截器的intercept()方法实现中,又会递归去调用传入链条的proceed()方法,直到链条执行结束。

经过上述分析,拦截器的职责也就显而易见了,重点是intercept(),以Response的返回作为分界,

  1. 上部分:封装Request
  2. 分界线:向下层传递Requset,并返回Response
  3. 下部分:处理返回的Response

原 创 不 易 , 还 希 望 各 位 大 佬 支 持 一 下 \textcolor{blue}{原创不易,还希望各位大佬支持一下}

👍 点 赞 , 你 的 认 可 是 我 创 作 的 动 力 ! \textcolor{green}{点赞,你的认可是我创作的动力!}

⭐️ 收 藏 , 你 的 青 睐 是 我 努 力 的 方 向 ! \textcolor{green}{收藏,你的青睐是我努力的方向!}

✏️ 评 论 , 你 的 意 见 是 我 进 步 的 财 富 ! \textcolor{green}{评论,你的意见是我进步的财富!}

下篇预告:分析第一个拦截器-RetryAndFollowUpInterceptor ,分析其如何重试和重定向

下篇文章已更新OkHttp原理第三篇—RetryAndFollowUpInterceptor

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
>