okhttp 网络请求解析
前言
虽然我们常常使用 Retrofit 配合 okhttp 一起使用,但 okhttp 其实有自己完整的 okhttp 请求流程
这篇文章的目的就是深入解读 okhttp 从应用层到底层的请求流程,同时解析 okhttp 中重要的组成部分 Interceptor 的工作原理
okhttp 基本使用
构造一个 okhttpClient
1 | public final OkHttpClient client = new OkHttpClient.Builder() |
通过 client 去执行网络请求
1 | // 同步请求 |
流程解析
okhttp 网络请求的发生在 OkHttpClient.newCall 方法返回的 Call 对象执行的同步 execute 或者异步 enqueue 方法,而 Call 是一个接口,那我们追踪到 OkHttpClient.newCall 方法查找 Call 的实例对象
OkHttpClient.newCall 方法
1 | public Call newCall(Request request) { |
RealCall.newRealCall 静态方法
1 | static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) { |
找到真正的 Call 实例,我们继续追踪 execute 方法
RealCall.execute 方法
1 |
|
继续追踪到 Dispatcher.executed 方法
Dispatcher.executed 方法
1 | synchronized void executed(RealCall call) { |
这里 RealCall 被加入到了一个叫 runningSyncCalls 的队列,从字面意义上看就是运行中的同步队列,我们的追踪到这里只能结束了,难道说由于这是个同步方法,所以触发流程并不在这里,这里只是记录了一下运行中的请求
这样的话只能返回去,从 getResponseWithInterceptorChain 方法追踪
RealCall.getResponseWithInterceptorChain 方法
1 | Response getResponseWithInterceptorChain() throws IOException { |
追踪到 Interceptor.Chain.proceed 方法
1 | public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec, |
这里需要提到 okhttp 的设计模式——责任链模式,责任链的定义是使对象有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。在这里一大堆 Interceptor 形成了 InterceptorChain,而请求则会沿着链子传播处理,如果用图表示
在 Chain.proceed 中会生成下一个 nextChain,然后会调用对应的 Interceptor.intercept 方法并传入 nextChain,以伪代码展示 Interceptor.intercept 方法
Interceptor.intercept 方法
1 | public Response intercept(Chain chain) throws IOException { |
这就完成了一个链式处理外层 intercept 提供处理后的request 给内层,内层返回 response 给外层,所以 intercept 的添加顺序会影响调用顺序,最先添加的则是最外层调用,而且我们可以得知最终的网络调用是在 CallServerInterceptor 里,使用了 Okio 操作 io 流。
现在我们回到 enqueue 异步操作方法去看看异步是如何执行的,RealCall 中,只是调用了 client.dispatcher().enqueue(new AsyncCall(responseCallback)),而真正生成调用链应该会在 Dispatch.enqueue 中,最终追踪到 Dispatch.enqueue 方法中
Dispatch.enqueue 方法
1 | synchronized void enqueue(AsyncCall call) { |
分析 AsyncCall 的数据结构可以,真正的调用是在 AsyncCall.execute 方法中
AsyncCall.execute 方法
1 | protected void execute() { |
可以看到这里面的调用方法和同步方法里面基本一样,只是返回值交给了 callback 处理
结语
我们已经解析了请求整个请求过程,当然具体的各个 Interceptor 的逻辑没有深究,如果感兴趣可以去看看源码,至此,网络三剑客的解析已经全部完成