OKHttp源码解析(一)
来源:互联网 发布:淘宝文案兼职 编辑:程序博客网 时间:2024/09/21 06:32
在上一篇博客中,我们介绍了OKHttp的基本用法,这一篇我们将从源码角度来看下OKHttp是如何完成一些列的网络的操作的。
我们知道在okhttpclient同步请求和异步请求调用的接口不一样,但它们最后都是殊途同归地走到Call里面的
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> Response <span class="hljs-title" style="box-sizing: border-box;">getResponseWithInterceptorChain</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> forWebSocket) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throws</span> IOException { Call.ApplicationInterceptorChain chain = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Call.ApplicationInterceptorChain(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.originalRequest, forWebSocket); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> chain.proceed(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.originalRequest); }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>
首先我们来看看调用execute和enqueue是如何走到`getResponseWithInterceptorChain的。
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Response <span class="hljs-title" style="box-sizing: border-box;">execute</span>() <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throws</span> IOException { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">synchronized</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>) { <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//执行过不能再执行</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.executed) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throw</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> IllegalStateException(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Already Executed"</span>); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.executed = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>; } Response var2; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> { <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//把这次请求加入到分发器里</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.client.getDispatcher().executed(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>); Response result = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.getResponseWithInterceptorChain(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(result == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throw</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> IOException(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Canceled"</span>); } var2 = result; } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">finally</span> { <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.client.getDispatcher().finished(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> var2; }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li></ul>
上面代码14行用到了一个从OkHttpClient获得的Dispatcher然后把它加入到分发器里面的队列 executedCalls中,在完成的时候会remove掉
<code class="hljs sql has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">synchronized void executed(<span class="hljs-operator" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Call</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">call</span>) { this.executedCalls.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">add</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">call</span>);</span> } synchronized void finished(<span class="hljs-operator" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Call</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">call</span>) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(!this.executedCalls.remove(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">call</span>)) { throw new AssertionError(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Call wasn\'t in-flight!"</span>);</span> } }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>
再来看看异步如何走到getResponseWithInterceptorChain
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">enqueue</span>(Callback responseCallback) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.enqueue(responseCallback, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> enqueue(Callback responseCallback, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> forWebSocket) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">synchronized</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.executed) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throw</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> IllegalStateException(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Already Executed"</span>); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.executed = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>; } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.client.getDispatcher().enqueue(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Call.AsyncCall(responseCallback, forWebSocket, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>)); }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li></ul>
是不是和同步很像,最后都是调用分发器的enqueue,但和同步不同的是,同步传入enqueue方法的参数是Call,异步传入的是AsyncCall,这个是什么呢,这个是Call里面的一个内部类,而且是一个继承了Runnable的内部类,我们先来看看这个execute怎么操作
<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">synchronized void enqueue(AsyncCall <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">call</span>) { //判断当前运行的线程是否超过最大线程数,以及同一个请求是否要超过相同请求同时存在的最大数目 if(this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.runningCalls</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.size</span>() < this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.maxRequests</span> && this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.runningCallsForHost</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">call</span>) < this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.maxRequestsPerHost</span>) { this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.runningCalls</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.add</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">call</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> //将请求放到线程池里运行 this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getExecutorService</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.execute</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">call</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> } else { //不满足运行条件放到后备队列里 this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.readyCalls</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.add</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">call</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> } }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li></ul>
从上面代码我们看到异步请求是有条件限制的,默认最多64个请求,而同一个请求默认最多同时存在5个
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> <span class="hljs-title" style="box-sizing: border-box;">runningCallsForHost</span>(AsyncCall call) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> result = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; Iterator var3 = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.runningCalls.iterator(); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span>(var3.hasNext()) { AsyncCall c = (AsyncCall)var3.next(); 通过比较每个请求的url,一样代表同一个请求 <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(c.host().equals(call.host())) { ++result; } } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> result; }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li></ul>
下面的两个参数可以通过从OKHttpClient getDispatch得到分发器,并根据分发器提提供的设置方法去修改,修改比较简单就不贴代码了 。
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> maxRequests = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">64</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> maxRequestsPerHost = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>
再来看看AsyncCall 的run里面的代码
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">run</span>() { String oldName = Thread.currentThread().getName(); Thread.currentThread().setName(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.name); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.execute(); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">finally</span> { Thread.currentThread().setName(oldName); } }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li></ul>
显然AsyncCall的execute才是核心
<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">protected void execute() { boolean signalledCallback = false<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> try { Response e = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Call</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.this</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getResponseWithInterceptorChain</span>(this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.forWebSocket</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> if(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Call</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.this</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.canceled</span>) { signalledCallback = true<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>//取消<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">call</span>调用onFailure回调 this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.responseCallback</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.onFailure</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Call</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.this</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.originalRequest</span>, new IOException(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Canceled"</span>))<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> } else { signalledCallback = true<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> //请求成功,回调onResponse this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.responseCallback</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.onResponse</span>(e)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> } } catch (IOException var6) { if(signalledCallback) { Internal<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.logger</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.log</span>(Level<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.INFO</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Callback failure for "</span> + <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Call</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.this</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.toLoggableString</span>(), var6)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> } else { this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.responseCallback</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.onFailure</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Call</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.this</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.engine</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getRequest</span>(), var6)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> } } finally { //完成请求,调用finish,从队列中清空 <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Call</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.this</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.client</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getDispatcher</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.finished</span>(this)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> } }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li></ul>
在代码第五行我们又看到了getResponseWithInterceptorChain。
我们继续看getResponseWithInterceptorChain里面的实现
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> Response <span class="hljs-title" style="box-sizing: border-box;">getResponseWithInterceptorChain</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> forWebSocket) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throws</span> IOException { Call.ApplicationInterceptorChain chain = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Call.ApplicationInterceptorChain(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.originalRequest, forWebSocket); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> chain.proceed(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.originalRequest); }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>
创建了一个ApplicationInterceptorChain ,并且第一个参数传入0,这个0是有特殊用法的,涉及到OKHttp里面的一个功能叫做拦截器,从getResponseWithInterceptorChain这个名字里其实也能看出一二。先看看proceed做了什么
<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">public Response proceed(Request request) throws IOException { //先判断是否每个拦截器都有对应的处理,没有的话先继续新建ApplicationInterceptorChain ,并执行当前拦截器的intercept方法 if(this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.index</span> < <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Call</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.this</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.client</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.interceptors</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.size</span>()) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Call</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.ApplicationInterceptorChain</span> chain = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Call</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.this</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.new</span> ApplicationInterceptorChain(this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.index</span> + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, request, this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.forWebSocket</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> return ((Interceptor)<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Call</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.this</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.client</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.interceptors</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.get</span>(this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.index</span>))<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.intercept</span>(chain)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> } else { return <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Call</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.this</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getResponse</span>(request, this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.forWebSocket</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> } }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>
这里碰到一个拦截器,OKHttp增加了一个拦截器机制,先来看看官方文档对Interceptors 的解释
Interceptors are a powerful mechanism that can monitor, rewrite, and retry calls.
解释下就是拦截器可以用来转换,重试,重写请求的机制,再来看看官方文档里提供的例子
首先自定义一个拦截器用于打印一些发送信息
<code class="hljs axapta has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">LoggingInterceptor</span> <span class="hljs-inheritance" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">implements</span></span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Interceptor</span> {</span> @Override <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Response intercept(Chain chain) throws IOException { Request request = chain.request(); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> t1 = System.nanoTime(); logger.info(String.format(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Sending request %s on %s%n%s"</span>, request.url(), chain.connection(), request.headers())); Response response = chain.proceed(request); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> t2 = System.nanoTime(); logger.info(String.format(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Received response for %s in %.1fms%n%s"</span>, response.request().url(), (t2 - t1) / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1e6</span>d, response.headers())); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> response; }}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li></ul>
然后使用的时候把它添加到okhttpclient
<code class="hljs vbscript has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">OkHttpClient client = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> OkHttpClient();client.interceptors().add(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> LoggingInterceptor());<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">Request</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">request</span> = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">Request</span>.Builder() .url(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"http://www.publicobject.com/helloworld.txt"</span>) .header(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"User-Agent"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"OkHttp Example"</span>) .build();<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">Response</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">response</span> = client.newCall(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">request</span>).<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">execute</span>();<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">response</span>.body().close();</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li></ul>
当我们执行到proceed,就会去判断是否有拦截器有的话先执行拦截器里的intercept,而在intercept里一般会进行一些自定义操作并且调用procced去判断是否要继续执行拦截器操作还是直接去获取网络请求,我们看看procced做了什么
<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">public Response proceed(Request request) throws IOException {//判断还有拦截器需要执行不,生成新的ApplicationInterceptorChain并调用它的intercept去执行用户定义的操作 if(this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.index</span> < <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Call</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.this</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.client</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.interceptors</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.size</span>()) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Call</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.ApplicationInterceptorChain</span> chain = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Call</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.this</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.new</span> ApplicationInterceptorChain(this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.index</span> + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, request, this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.forWebSocket</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> return ((Interceptor)<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Call</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.this</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.client</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.interceptors</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.get</span>(this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.index</span>))<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.intercept</span>(chain)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> } else { return <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Call</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.this</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getResponse</span>(request, this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.forWebSocket</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> } }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>
上面的例子执行结果如下
<code class="hljs http has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-attribute" style="box-sizing: border-box;">INFO</span>: <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">Sending request http://www.publicobject.com/helloworld.txt on null</span><span class="hljs-attribute" style="box-sizing: border-box;">User-Agent</span>: <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">OkHttp Example</span><span class="http" style="box-sizing: border-box;"><span class="hljs-attribute" style="box-sizing: border-box;">INFO</span>: <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">Received response for https://publicobject.com/helloworld.txt in 1179.7ms</span><span class="hljs-attribute" style="box-sizing: border-box;">Server</span>: <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">nginx/1.4.6 (Ubuntu)</span><span class="hljs-attribute" style="box-sizing: border-box;">Content-Type</span>: <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">text/plain</span><span class="hljs-attribute" style="box-sizing: border-box;">Content-Length</span>: <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">1759</span><span class="hljs-attribute" style="box-sizing: border-box;">Connection</span>: <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">keep-alive</span></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>
拦截器的整个机制如下图
上图中把拦截器氛围应用拦截器和网络拦截器,其实这个取决于你在拦截器里做了哪方面的操作,比如改变了请求头部之类的就可以成为网络拦截器。
在处理完拦截器操作后,就进入到重要的getResponse方法,真正的去进行发送请求,处理请求,接收返回结果。
<code class="hljs d has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">Response getResponse(Request request, boolean forWebSocket) throws IOException { RequestBody <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">body</span> = request.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">body</span>(); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">body</span> != <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">null</span>) { <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果是post方式,处理一些头部信息</span> Builder followUpCount = request.newBuilder(); MediaType response = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">body</span>.contentType(); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(response != <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">null</span>) { followUpCount.header(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Content-Type"</span>, response.toString()); } <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">long</span> followUp = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">body</span>.contentLength(); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(followUp != -<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1L</span>) { followUpCount.header(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Content-Length"</span>, Long.toString(followUp)); followUpCount.removeHeader(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Transfer-Encoding"</span>); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> { followUpCount.header(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Transfer-Encoding"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"chunked"</span>); followUpCount.removeHeader(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Content-Length"</span>); } request = followUpCount.build(); } <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//新建HttpEngine,用于进行发送请求和读取答复的细节处理</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.engine = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> HttpEngine(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.client, request, <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">false</span>, <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">false</span>, forWebSocket, (Connection)<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">null</span>, (RouteSelector)<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">null</span>, (RetryableSink)<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">null</span>, (Response)<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">null</span>); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> var11 = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span>(!<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.canceled) { HttpEngine var13; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> { <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//发送请求</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.engine.sendRequest(); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//读取答复</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.engine.readResponse(); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (RequestException var8) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throw</span> var8.getCause(); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (RouteException var9) { var13 = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.engine.recover(var9); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(var13 != <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">null</span>) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.engine = var13; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">continue</span>; } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throw</span> var9.getLastConnectException(); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (IOException var10) { var13 = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.engine.recover(var10, (Sink)<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">null</span>); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(var13 != <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">null</span>) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.engine = var13; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">continue</span>; } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throw</span> var10; } Response var12 = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.engine.getResponse(); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//得到该请求对应的后续请求,比如重定向之类的</span> Request var14 = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.engine.followUpRequest(); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(var14 == <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">null</span>) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(!forWebSocket) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.engine.releaseConnection(); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> var12; } ++var11; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(var11 > <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">20</span>) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throw</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ProtocolException(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Too many follow-up requests: "</span> + var11); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(!<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.engine.sameConnection(var14.url())) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.engine.releaseConnection(); } Connection connection = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.engine.close(); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.engine = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> HttpEngine(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.client, var14, <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">false</span>, <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">false</span>, forWebSocket, connection, (RouteSelector)<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">null</span>, (RetryableSink)<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">null</span>, var12); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.engine.releaseConnection(); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throw</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> IOException(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Canceled"</span>); }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li></ul>
可以看到如果是post请求,先做一定的头部处理,然后新建一个HttpEngine去处理具体的操作,通过sendRequest发送具体请求操作,readResponse对服务器的答复做一定处理,在代码52行处getResponse得到从服务器返回的Response,讲到这里,我们整个的流程大概疏通了,代码贴了很多,简单的可以用下面一张图概括
整体看就是根据用户的请求Request放入到指定队列,并使用拦截器链的方式去执行我们的请求操作。
上图中的sendRequest,缓存处理,readReponse,介于篇幅问题(本来想一篇写完的,结果发现篇幅好长,分几篇完成吧)将在后续的文章中继续介绍。
- OKHttp源码解析(一)
- OKHttp源码解析(一)
- OKHttp源码解析(一)
- OKHttp源码解析(一)
- OkHttp源码解析(一)
- okhttp源码解析(一)
- Okhttp源码简单解析(一)
- OkHttp完全解析(八)源码解析一
- Android网络框架:OKHttp源码简单解析(一)
- 安卓面试清单----OKHttp源码解析(一)
- OKHttp源码解析一(网络请求篇)
- OkHttp完全解析(一)OkHttp简介
- OKHttp源码解析(二)
- OKHttp源码解析(三)
- OKHttp源码解析(二)
- OKHttp源码解析(三)
- OKHttp源码解析(二)
- OkHttp源码解析(1)
- java排序算法
- 图像点击跟踪系统
- NSCalendar 获取当前时间,年,月,日与当前时间对比
- C#中对sqlserver进行增删改查
- 最核心的是要熟悉和掌握HTTP协议
- OKHttp源码解析(一)
- 华为机试---生成格雷码
- 242. Valid Anagram 有效的Anagram
- 设计模式- 适配器模式
- 递归调用的方式遍历SD卡上的所有图片
- OKHttp源码解析(二)
- 你可能并不需要消息队列
- Stanford 中文分词
- Android中LocalSocket使用