浅析 OkHttp 源码 - Callback 的调用流程

前言

上一篇文章 《关于 OkHttp 和 Retrofit 的使用,你需要注意的点》 讲到了 拦截器中抛出非 IOException 异常而且使用了 enqueue 进行异步请求的时候 OkHttp 会直接使 App crash(使用 execute 方法进行同步请求的时候如果没有捕获非 IOException 异常的话也是一样的),那么 Callback 的 onFailure 方法和 onResponse 方法究竟会在什么时候回调呢?本节咱们就来看看 OkHttp Callback 调用的源码,一探究竟!


添加依赖

1
2
// OkHttp 框架:https://github.com/square/okhttp
implementation 'com.squareup.okhttp3:okhttp:4.9.3'

简单使用

老样子,咱们先写一个最简单的 OkHttp 调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private val mClient = OkHttpClient.Builder()
.build()

fun okHttpTest() {
val request = Request.Builder()
.url("https://www.baidu.com/")
.build()
mClient.newCall(request)
.enqueue(object : Callback {

override fun onFailure(call: Call, e: IOException) {
e.printStackTrace()
}

@Throws(IOException::class)
override fun onResponse(call: Call, response: Response) {
println("okHttpExceptionTest:response is ${response.body?.string()}")
}
})
}

然后,我们按住 Ctrl 并点击 enqueue 方法查看在哪里调用了这个 Callback。

图片描述


咦,居然是个 Call 接口,那行吧。咱们先看看这个 Call 接口是个啥玩意儿。我们想看这个 Call 接口是个啥之前,先看看它是怎么来的吧。


按住 Ctrl 然后鼠标点击 enqueue 方法之前的 newCall 方法。

图片描述


然后,我们尝试搜索 enqueue 这个方法,看看在哪里实现的。

图片描述


很明显,刚刚我们 new 的 Callback 被传入了 AsyncCall 这个类的构造方法中,那行呗,咱们继续往下跟。

图片描述


这个时候,我们尝试搜索一下 responseCallback 这个变量的 onFailure 方法在 AsyncCall 中的调用。

小技巧:在这里面如果搜不到它的调用的话,那么这个变量一定是被传递给另外一个类了。

图片描述


这里,我们可以看到 onFailure 方法在这个类里一共有 3 处调用,那么我们接下来看看剩下两处调用在哪里。

图片描述


以上就是 onFailure 回调方法的全部调用啦,看过 上一篇文章 的同学可能会注意到这些调用传入的全部都是 IOException


既然 onFailure 回调看完了,如法炮制,那我们再看看 onResponse 方法的调用吧。

图片描述


这里我们可以看到,回调 onResponse 方法的时候首先捕获了 IOException 这个异常,然后回调到 onFailure 方法,如果是非 IOException 的话,则会先调用 cancel 方法取消网络请求的调用,然后将该异常直接 throw 抛出。


我们看到调用 onResponse 之前先调用了 getResponseWithInterceptorChain 方法,从方法名翻译过来就是:使用拦截器链获得响应。


既然如此,那我们再去看看 getResponseWithInterceptorChain 方法里面的实现吧。

图片描述


可以看到,OkHttp 通过 client 的 interceptors 这个 get 方法拿到了一堆拦截器然后传给 RealInterceptorChain 这个 真正的拦截器链 进行调用处理。

图片描述


那么,这个 client 变量是个啥呢?

图片描述


还记得我们最开始想看 newCall 方法的时候创建了一个 RealCall 对象的实例吗?第一个参数传入了 “this” 。没错!这个 “this” 正是我们自己最开始创建的 “mClient” !

图片描述


这个时候我们就能从源码调用的层面解释为啥在拦截器中抛出非 IOException 异常的时候会导致 APP crash 了。


总结

在看源码时如果遇到返回的是接口的情况,我们应该先去看它是怎么被创建(获取到)的,然后去看它的具体实现。


如果对你有帮助的话,欢迎一键三连+关注哦~


浅析 OkHttp 源码 - Callback 的调用流程
https://blog.funkt.cn/2022/08/27/1563753906545102850/
作者
anjiemo
发布于
2022年8月28日
许可协议
未经作者授权,禁止转载