以下基于okp 3.14.9 版本的分析
//要提交的正文
String content = "我叫靓仔";
//定义正文的类型为json
RequestBody body = RequestBody.create(
MediaType.parse("application/json"), content);
//构建成一个请求
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
//将请求塞给call,然后进入异步请求
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});
一般来说,我们会通过类似以上的代码,去进行网络请求。
我们留意到,在 okHttpClient.newCall(request).enqueue 这行代码里,最终通过 enqueue方法完成请求了。嗯,好像是这样子,我们跟着点进去看看 enqueue方法
enqueue 方法上备注了一堆注释,机器翻译:
安排在未来某个时间点执行的请求。
dispatcher程序定义请求何时运行:通常是立即运行,除非当前有几个其他请求正在执行。
此客户端稍后将使用 HTTP 响应或失败异常回调responseCallback 。
抛出:
IllegalStateException – 当调用已经执行时。
大概的意思就是:这个请求会在将来某个时候执行的
这个 enqueue 其实是接口 Call 里面的一个方法,那么,也就意味着应该会有某个具体的实现类来实现这个接口的骚操作,那么,我们跟进去看看这个实现类是谁
你会发现,这实现类叫 RealCall, 因为这货没有文档注释,所以,我们就暂时忽略它是干嘛的。我们先看看 enqueue 的具体逻辑做了啥,我们盲猜方法里的最后一行才是请求的关键
client.dispatcher().enqueue(new AsyncCall(responseCallback));
嗯,所以,我们又得进去看看这个 enqueue 方法做了啥
在 enqueue 方法里,我们发现,所在类的名称叫 Dispatcher 我们继续发现新大陆 promoteAndExecute 这个方法,所以进去
机器翻译一下注释:
将符合条件的调用从readyAsyncCalls为runningAsyncCalls并在 executor 服务上运行它们。不能同步调用,因为执行调用可以调用用户代码。
回报:
如果调度程序当前正在运行调用,则为 true。
大概意思就是:这个方法用来将 readyAsyncCalls 转为 runningAsyncCalls ?
不过为啥要转?这两个又是啥东西?先不管吧,不然这么多看晕我哦。 我看看这行代码:
asyncCall.executeOn(executorService());
点进去看下 executeOn 是个啥
机器翻译一下注释:
尝试在executorService上将此异步调用加入队列。如果执行程序已通过将调用报告为失败而关闭,这将尝试进行清理。
注释,....算了,直接看try了啥,
executorService.execute(this);
这个 executorService 呢,是个线程池,别问我怎么知道的,因为人家的类型写着是 ExecutorService
既然这个是线程池,那么,这个线程池的 execute 方法是干嘛用的呢? 进去看看方法描述
机器翻译:
在将来的某个时间执行给定的命令。根据Executor实现的判断,该命令可以在新线程、池线程或调用线程中执行。
参数:
command – 可运行的任务
抛出:
RejectedExecutionException – 如果此任务不能被接受执行
NullPointerException – 如果命令为空
你看,这个方法其实是接收一个线程作为参数,然后就跑起来了,说白了就是,调用了线程的run方法。咦,这么说来,
executorService.execute(this);
这个this,就是一个线程实例喽?那么,这个方法所在的类是什么呢?看下
我们看到这个类叫 AsyncCall ,继承自 NamedRunnable 然后,所以,按道理来讲,这个 NamedRunnable 理应是个线程,我看下
啧啧,你们看,NamedRunnable 实现了 Runnable 接口,流的是 Runnable 的血,同时,火力转移到 execute 这个方法,为啥呢?因为线程 run 起来的时候,调用它了,我们直接进去看看它的实现
万众瞩目,终于,看到了请求结果的回调了。
我们发现, Response 是通过 getResponseWithInterceptorChain 这个方法执行后,返回来的。同时,我们留意到,接着会通过 responseCallback 这个东西,将 Response 扔出去
那么这个 responseCallback ,其实就是
就是
没错,它其实就是我们一开始设置好的接收请求结果的回调接口 Callback 。
这是从okhttpClient执行异步请求的调用过程,不包含责任链的调度过程
RealCall.enqueue --》
Dispatcher.enqueue--》将线程AsyncCall放入准备队列中 promoteAndExecute--》判断是否超过总的最大请求数量以及单个服务器的最大请求数,如果都没超过,就放入运行队列中
RealCall.executeOn---》尝试将线程丢进线程池中,当然可能会被拒绝,拒绝的话,就从运行队列中踢出
ExecutorService.execute--》线程池开始执行线程 ,触发线程NamedRunnable的运行
NamedRunnable.run---》 run方法调用了一个execute方法,execute方法的具体实现在RealCall.execute
RealCall.execute--》主要是做了两个种回调给开发者使用,成功时回调onResponse ,失败时回调 onFailure getResponseWithInterceptorChain--》
Interceptor.Chain.proceed --》一发入魂,直接进入责任链调用。这里开始进入责任链的逻辑了,可能会比较绕,建议先看看责任链的简单示例,方便理解该模式的运行情况
至此,瞎几把分析的大概请求流程到此为止?不过, getResponseWithInterceptorChain 这个方法到底是何方神圣?等我回来!



