Okhttp源码浅析

Posted by dingqiang.l on April 3, 2017

写在前面

写这篇文章完全是让自己对Okhttp进一步的理解,同时也希望帮助对这个库感到迷茫的童鞋。有不对的地方希望大牛们指正。

做过Android的想必对Okhttp很熟悉,没错,它是一个网络请求库,但是值得我们注意的是,这个库和以前我们使用的Volley和android-async-http等库的级别不一样,Volley和android-async-http是基于HttpClient或者HttpUrlConnection的封装,而Okhttp确是基于Sokect的封装。下面简单分析Okhttp源码

那么我们从最简单的请求开始,Okhttp的请求分为了同步(execute)和异步请求(enqueue),它们的请求接口是不一样的,但是两者经过一系列的处理后都走到的Call的实现类RealCall中。

getResponseWithInterceptorChain.png

以下分别分析同步(execute)和异步请求(enqueue)部分重要源码 首先是execute()方法:

realCall_execute.png

以上看到了我们关心的getResponseWithInterceptorChain()方法。

需要注意的是 “this.client.getDispatcher().executed(this)”这行,它表示的是从OkHttpClient获得的Dispatcher,然后把它加入到分发器里面的队列 executedCalls中,在完成的时候会remove掉

然后是enqueue()方法:

realCall_enqueue.png

异步的实现与同步类似,而不同的是execute传入的是RealCall,enqueue传入的是AsyncCall)(是Call的一个内部类,并且实现了Runnable接口)。

以下是enqueue的实现 AsyncCall_enqueue.png

最终会我们会看到enqueue的核心代码:

Execute_enqueue.png

至此,是不是和execute很像了,同样我们也看到了对getResponseWithIntercetorChain的调用。需要注意的是,enqueue执行到最后同样会执行到execute。

下面开始对getResponseWithIntercetorChain分析

创建了一个ApplicationInterceptorChain ,并且第一个参数传入0,这个0是有特殊用法的,涉及到OKHttp里面的一个功能”拦截器”。再 看看proceed做了什么

getResponseWithInterceptor_proceed.png

在此可以看到Okhttp增加了个Application级的拦截器,我们可以根据需要自定义一个拦截器,拦截我们需要的信息,使用的时候用OkhttpClient add我们定义好的Intercept即可。

大体流程:

1.app 发出请求(Request),Okhttp内部处理,先读取缓存,如果有缓存则直接从缓存中返回。如果没有缓存则进行以下步骤; 2.向服务器发出请求(Request),服务器响应(Response),Okhttp内部处理后返回到app。

content.png

再进去proceed中的getResponse方法

getResponse.png

可以看到,如果发出的请求是post,那一定是经过头部处理,然后新建一个HttpEngine去处理具体的操作,通过sendRequest发送具体请求操作,readResponse对服务器的答复做一定处理,在代码31行处getResponse得到从服务器返回的Response。至此,一个请求响应流程大概就是这样了。

整体看就是根据用户的请求Request放入到指定队列,并使用拦截器链的方式去执行我们的请求操作。

写在最后

以上只是对Okhttp做了个粗浅的介绍,当然一篇文章也不可能将这个库讲解完,像拦截器、缓存等等都没有深入解析,这些内容只能放到下篇文章讲解了。