当前位置: 萬仟网 > IT编程>移动开发>Android > Okhttp3源码解析(3)-Call分析(整体流程)

Okhttp3源码解析(3)-Call分析(整体流程)

2019年08月23日 18:24  | 萬仟网IT编程  | 我要评论
### 前言 前面我们讲了 [okhttp的基本用法](https://www.jianshu.com/p/8e404d9c160f) [okhttp3源码解析(1)-okhttpclient分析](https://www.jianshu.com/p/bf1d01b79ce7) [okhttp3源码解析(2)-request分析](https://www.jianshu.com/p/5a85345c8ea7) ### newcall分析 ##### call初始化 我们首先看一下在哪用到了call: ``` final call call = okhttpclient.newcall(request); ``` 想起来了吧?无论是get还是post请求 都要生成call对象,在上面我们发现call实例需要一个`okhttpclient`与`request`实例 ,我们先点进call类去看看: ``` public interface call extends cloneable { //请求 request request(); //同步 response execute() throws ioexception; //异步 void enqueue(callback responsecallback); //取消请求 void cancel(); //是否在请求过程中 boolean isexecuted(); //是否取消 boolean iscanceled(); call clone(); //工厂接口 interface factory { call newcall(request request); } } ``` 我们发现call是个接口, 并定义了一些方方法(方法含义在注释上)。 我们继续看`newcal()`方法 ``` @override public call newcall(request request) { return realcall.newrealcall(this, request, false /* for web socket */); } ``` 继续点击`newrealcall()`去: ``` private realcall(okhttpclient client, request originalrequest, boolean forwebsocket) { this.client = client; this.originalrequest = originalrequest; this.forwebsocket = forwebsocket; this.retryandfollowupinterceptor = new retryandfollowupinterceptor(client, forwebsocket); } static realcall newrealcall(okhttpclient client, request originalrequest, boolean forwebsocket) { // safely publish the call instance to the eventlistener. realcall call = new realcall(client, originalrequest, forwebsocket); call.eventlistener = client.eventlistenerfactory().create(call); return call; } ``` 从代码中我们发现在`newrealcall()`中初始化了`realcall`,`realcall`中初始化了`retryandfollowupinterceptor` : - client: okhttpclient 实例 - originalrequest : 最初的request - forwebsocket :是否支持websocket通信 - retryandfollowupinterceptor 从字面意思来说, 是重试和重定向拦截器 ,至于它有什么作用我们继续往下看 ### 同步请求分析 ``` response response = call.execute(); ``` 我们点进`execute()`中查看: ``` @override public response execute() throws ioexception { synchronized (this) { if (executed) throw new illegalstateexception("already executed"); executed = true; } capturecallstacktrace(); eventlistener.callstart(this); try { client.dispatcher().executed(this); response result = getresponsewithinterceptorchain(); if (result == null) throw new ioexception("canceled"); return result; } catch (ioexception e) { eventlistener.callfailed(this, e); throw e; } finally { client.dispatcher().finished(this); } } ``` 从上面代码得知步骤: (1).通过 ` synchronized ` 保证线程同步,判断是否已经执行过 ,如果是直接抛异常 (2). `capturecallstacktrace();` 字面意思:捕获调用堆栈跟踪,我们通过源码发现里面涉及到了`retryandfollowupinterceptor` (3). ` eventlistener` 回调` callstart()` (4). `client.dispatcher().executed(this);` 看到了`dispatcher`是不是很熟悉?之前在分析`okhttpclient`初始化的时候遇到了,我们点击`executed()`方法进去: ``` synchronized void executed(realcall call) { runningsynccalls.add(call); } ``` 发现把我们传进来的`realcall`放到了`runningsynccalls`队列中,从字面意思来说就是正在运行的同步的调用队列中,为什么说是队列呢? : ``` private final deque runningsynccalls = new arraydeque<>(); ``` > deque即双端队列。是一种具有队列和栈的性质的数据结构。双端队列中的元素可以从两端弹出,相比list增加[]运算符重载。 (5).我们回到`execute()`继续往下分析,剩下的代码我们提取出三行代码: - `equesr result = getresponsewithinterceptorchain();` 生成一个response 实例 - `eventlistener.callfailed(this, e);` :eventlistener的callfailed回调 - `client.dispatcher().finished(this);` :dispatcher实例的finished方法 不难看出,**`getresponsewithinterceptorchain()`**一定是此方法中的**核心**,字面意思是获取拦截器链的响应,这就明白了,就是**通过拦截器链处理后返回response** ![](https://img2018.cnblogs.com/blog/1312938/201908/1312938-20190823173540636-96122427.png) ###### getresponsewithinterceptorchain() 分析 ``` response getresponsewithinterceptorchain() throws ioexception { // build a full stack of interceptors. list interceptors = new arraylist<>(); interceptors.addall(client.interceptors()); //自定义 interceptors.add(retryandfollowupinterceptor); //错误与跟踪拦截器 interceptors.add(new bridgeinterceptor(client.cookiejar())); //桥拦截器 interceptors.add(new cacheinterceptor(client.internalcache())); //缓存拦截器 interceptors.add(new connectinterceptor(client)); //连接拦截器 if (!forwebsocket) { interceptors.addall(client.networkinterceptors()); //网络拦截器 } interceptors.add(new callserverinterceptor(forwebsocket)); //调用服务器拦截器 interceptor.chain chain = new realinterceptorchain(interceptors, null, null, null, 0, originalrequest, this, eventlistener, client.connecttimeoutmillis(), client.readtimeoutmillis(), client.writetimeoutmillis()); return chain.proceed(originalrequest); } ``` 从上面代码不难看出, 对最初的request做了层层拦截,每个拦截器的原理我们放在以后的章节去讲, 这里就不展开了! 这里需要强调的一下 ` interceptors.addall(client.interceptors()); ` ,` client.interceptors()` 是我们自定义的拦截器 它是在哪定义的?如何添加?我们去okhttpclient类中发现: ![](https://img2018.cnblogs.com/blog/1312938/201908/1312938-20190823173540985-1903691954.png) 可以通过初始化`okhttpclient`实例 ` .addinterceptor`的形式 添加。 ### 异步请求分析 ``` call.enqueue(new callback() { @override public void onfailure(call call, ioexception e) { log.d("okhttp_error",e.getmessage()); } @override public void onresponse(call call, response response) throws ioexception { gson gson=new gson(); log.d("okhttp_success",response.body().string()); } }); ``` 点击`enqueue()`查看: ``` @override public void enqueue(callback responsecallback) { synchronized (this) { if (executed) throw new illegalstateexception("already executed"); executed = true; } capturecallstacktrace(); eventlistener.callstart(this); client.dispatcher().enqueue(new asynccall(responsecallback)); } ``` (1).通过 ` synchronized ` 保证线程同步,判断是否已经执行过 ,如果是直接抛异常 (2). `capturecallstacktrace();` 字面意思:捕获调用堆栈跟踪,我们通过源码发现里面涉及到了`retryandfollowupinterceptor` (3). ` eventlistener` 回调` callstart()` (4). `client.dispatcher().enqueue(new asynccall(responsecallback));` 调用了`dispatcher.enqueue()`并传入了一个**`new asynccall(responsecallback)`**实例,点击**asynccall**查看: **asynccall 是realcall的内部类!** ``` final class asynccall extends namedrunnable { private final callback responsecallback; asynccall(callback responsecallback) { super("okhttp %s", redactedurl()); this.responsecallback = responsecallback; } string host() { return originalrequest.url().host(); } request request() { return originalrequest; } realcall get() { return realcall.this; } @override protected void execute() { boolean signalledcallback = false; try { response response = getresponsewithinterceptorchain(); if (retryandfollowupinterceptor.iscanceled()) { signalledcallback = true; responsecallback.onfailure(realcall.this, new ioexception("canceled")); } else { signalledcallback = true; responsecallback.onresponse(realcall.this, response); } } catch (ioexception e) { if (signalledcallback) { // do not signal the callback twice! platform.get().log(info, "callback failure for " + tologgablestring(), e); } else { eventlistener.callfailed(realcall.this, e); responsecallback.onfailure(realcall.this, e); } } finally { client.dispatcher().finished(this); } } } ``` `asynccall`继承了`namedrunnable` ,我们看下`namedrunnable`是什么: ``` public abstract class namedrunnable implements runnable { protected final string name; public namedrunnable(string format, object... args) { this.name = util.format(format, args); } @override public final void run() { string oldname = thread.currentthread().getname(); thread.currentthread().setname(name); try { execute(); } finally { thread.currentthread().setname(oldname); } } protected abstract void execute(); } ``` 原来`namedrunnable` 实现了`runnable` 接口 是个线程类,在`run()`中 添加了抽象的`execute();`方法,看到这里 我们应该有一个反应,那就是**asynccall中具体的execute()应该在子线程执行** 我们继续分析,`client.dispatcher().enqueue(new asynccall(responsecallback));` 点击进入enqueue(): ``` synchronized void enqueue(asynccall call) { if (runningasynccalls.size() < maxrequests="" &&="" runningcallsforhost(call)="">< maxrequestsperhost)="" {="" runningasynccalls.add(call);="" executorservice().execute(call);="" }="" else="" {="" readyasynccalls.add(call);="" }="" }="" ```="" -="" `runningasynccalls`="" 正在运行的异步请求的队列="" -="" `maxrequests`="" 最大的请求数="" 64="" -="" `maxrequestsperhost`="" host最大请求数="" 5="" (可以通过get与set方式自定义设置)="" 如果正在运行的异步请求的队列大小低于64并且="" 正在请求的host数量低于5,就会执行(满足条件)="" ```="" runningasynccalls.add(call);="" executorservice().execute(call);="" ```="" 这里把="" `asynccall="" `实例添加到="" `runningasynccalls="" `中。="" `executorservice`="" 表示线程池="" 继续看="" `executorservice()`:="" ```="" public="" synchronized="" executorservice="" executorservice()="" {="" if="" (executorservice="=" null)="" {="" executorservice="new" threadpoolexecutor(0,="" integer.max_value,="" 60,="" timeunit.seconds,="" new="">(), util.threadfactory("okhttp dispatcher", false)); } return executorservice; } ``` 其实就是生成了executorservice 实例,这就明白了,`asynccall `实例放入线程池中执行了! 如果不满足上面的请求数等条件: ``` readyasynccalls.add(call); ``` 就会被添加到一个等待就绪的异步请求队列中,目的是什么呢??? 当然是等待时机再次添加到runningasynccalls中并放入线程池中执行,这块逻辑在 `asynccall `类中的 `execute() ` 至于原因我们继续往下看! ![](https://img2018.cnblogs.com/blog/1312938/201908/1312938-20190823173541531-1963303270.png) 刚才我们说了,如果条件满足, `asynccall `实例就会在线程池中执行(.start),那我们直接去看run()中的 `execute() ` : ``` @override protected void execute() { boolean signalledcallback = false; try { response response = getresponsewithinterceptorchain(); if (retryandfollowupinterceptor.iscanceled()) { signalledcallback = true; responsecallback.onfailure(realcall.this, new ioexception("canceled")); } else { signalledcallback = true; responsecallback.onresponse(realcall.this, response); } } catch (ioexception e) { if (signalledcallback) { // do not signal the callback twice! platform.get().log(info, "callback failure for " + tologgablestring(), e); } else { eventlistener.callfailed(realcall.this, e); responsecallback.onfailure(realcall.this, e); } } finally { client.dispatcher().finished(this); } } ``` 上面代码中得知, 首先通过层层拦截器链处理生成了`response`;然后通过一系列的判断,`responsecallback`进行`onresponse`与`onfailure`回调,最后调用的`dispatcher.finifshed()` 这里需要注意的是 **这里的`dispatcher.finifshed(this)`与同步中的`dispatcher.finifshed(this)`不一样** 参数不同。 ``` /** used by {@code asynccall#run} to signal completion. */ void finished(asynccall call) { finished(runningasynccalls, call, true); } ``` 我们继续看具体的finifshed()方法: ``` private void finished(deque calls, t call, boolean promotecalls) { int runningcallscount; runnable idlecallback; synchronized (this) { if (!calls.remove(call)) throw new assertionerror("call wasn't in-flight!"); if (promotecalls) promotecalls(); runningcallscount = runningcallscount(); idlecallback = this.idlecallback; } if (runningcallscount == 0 && idlecallback != null) { idlecallback.run(); } } ``` 在线程同步的情况下 执行了`promotecalls();`: ``` private void promotecalls() { if (runningasynccalls.size() >= maxrequests) return; // already running max capacity. if (readyasynccalls.isempty()) return; // no ready calls to promote. for (iterator i = readyasynccalls.iterator(); i.hasnext(); ) { asynccall call = i.next(); if (runningcallsforhost(call) < maxrequestsperhost)="" {="" i.remove();="" runningasynccalls.add(call);="" executorservice().execute(call);="" }="" if="" (runningasynccalls.size()="">= maxrequests) return; // reached max capacity. } } ``` 经过一系列的判断, 对等待就绪的异步队列进行遍历,生成对应的`asynccall `实例,并添加到runningasynccalls中,最后放入到线程池中执行! 这里就是我们上面说到的等待就绪的异步队列如何与runningasynccalls对接的逻辑。 ### 总结 ##### 同步请求流程: - 生成`call`实例realcall - `dispatcher.executed()`中的`runningsynccalls` 添加realcall到此队列中 - 通过 `getresponsewithinterceptorchain()` 对request层层拦截,生成response - 通过`dispatcher.finished()`,把call实例从队列中移除,返回最终的response ##### 异步请求流程: - 生成一个`asynccall(responsecallback)`实例(实现了runnable) - `asynccall`实例放入了`dispatcher.enqueue()`中,并判断`maxrequests` (最大请求数)`maxrequestsperhost`(最大host请求数)是否满足条件,如果满足就把`asynccall`添加到`runningasynccalls`中,并放入线程池中执行;如果条件不满足,就添加到等待就绪的异步队列,当那些满足的条件的执行时 ,在`dispatcher.finifshed(this)`中的`promotecalls();`方法中 对等待就绪的异步队列进行遍历,生成对应的`asynccall `实例,并添加到`runningasynccalls`中,最后放入到线程池中执行,一直到所有请求都结束。 至此okhttp整体流程就分析完了, 下一篇会分块去分析,希望对大家有所帮助... ![](https://img2018.cnblogs.com/blog/1312938/201908/1312938-20190823173541905-1601958458.png) 大家可以关注我的微信公众号:「秦子帅」一个有质量、有态度的公众号! ![公众号](https://img2018.cnblogs.com/blog/1312938/201908/1312938-20190823173542046-1151555749.jpg)

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

◎已有 0 人评论

Copyright © 2019  萬仟网 保留所有权利. 粤ICP备17035492号-1
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com