之前用到 Okhttp,但是一直没有深入了解,前段时间有时间看了下 Okhttp 的源码,这里记录分析下。主要从以下几方面分析吧:
- Okhttp 的简单使用
- Okhttp 访问网络的整体流程
- 一些重要类的介绍
- 一些总结
Okhttp 的简单使用
这里简单介绍下使用,然后从使用方法入手进行分析,详细的使用方法可以参考官方文档或者一些博客介绍,Okhttp使用
|
|
Okhttp 整体流程
从上面的使用我们可以看到,首先先 new 一个 OkhttpClient(),之后通过 OkhttpClient#newCall() 返回一个 Call 对象,通过 Call#enqueue()(异步) 或者 Call#execute()(同步) 返回访问结果。
OkhttpClient 的构造函数就是对一些设置进行初始化,所以直接从 OkhttpClient#newCall() 进行分析了。
|
|
可以看到,返回的是 Call 的实现类 RealCall,之后会调用 RealCall#enqueue() 和 RealCall#execute(),先看 RealCall#execute()
|
|
其中主要逻辑就是把请求加入队列中,之后通过 getResponseWithInterceptorChain() 执行请求,接下来就看这个函数的实现。
|
|
可以说这个方法是最核心的方法了,使用了链式处理,对请求的处理都封装成 Interceptor 并一层层调用,其中内置的有 BridgeInterceptor,CacheInterceptor(处理缓存),ConnectInterceptor(建立连接),CallServerInterceptor(处理具体请求和返回),同时我们也可以自己添加拦截器,是通过client.interceptors()添加进去的,接下来先看下拦截器是如何链式调用的,之后再具体看拦截器的内容。
|
|
从上面代码可以看出,先构建下一个 interceptor 的 RealInterceptorChain,然后获取到当前的 interceptors,执行 Interceptor#intercept(),并在其中用相同方法调用下一个 interceptor,这样层层调用下去,最后返回的就是被所有 Interceptor 处理过的 Response。
接下来我们看下 Interceptor#intercept() 中是如何处理请求的。重点分析 ConnectInterceptor 和 CallServerInterceptor。
介绍 ConnectInterceptor 之前先简单说下 RetryAndFollowUpInterceptor,下面看到的StreamAllocation 就是这里构建的。
先看 ConnectInterceptor
|
|
首先获取到前面创建的 StreamAllocatoin(这个类封装了连接,请求,流等),接着会调用 StreamAllocation#newStream(),这个方法里调用了 socket 连接到服务器,跟进看下,
|
|
再跟进 findHealthyConnection()
|
|
|
|
真正的连接过程在 newConnection#connect() 中
|
|
|
|
|
|
经过这么多函数调用,终于调到了 socket,之后再往回看 newStream()
|
|
在建立连接以后会构建 HttpCodec,Http1Codec 是对流的封装,这里用的 okio 里的 BufferedSource 和 BufferSink,分别可以对应到 IntputStream 和 OutputStream。
之后就返回到了 ConnectInterceptor#intercept(),他自己的已经处理完成,接着会调用下一个 Interceptor,也就是 CallServerInterceptor。
|
|
可以看到 CallServerIntercept 的主要作用就是把 request 数据写到输出流中发送到服务器,并从输入流里获取数据构建 response 返回。
整体流程就是这样,放一张流程图