Okhttp3源码解析(3)-Call分析(整体流程)
程序员文章站
2022-05-15 14:15:20
### 前言 前面我们讲了 [Okhttp的基本用法](https://www.jianshu.com/p/8e404d9c160f) [Okhttp3源码解析(1)-OkHttpClient分析](https://www.jianshu.com/p/bf1d01b79ce7) [Okhttp3源码 ......
### 前言
前面我们讲了
[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() (), 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) = 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)
上一篇: 蜜枣的功效是什么,如何自制蜜枣
下一篇: 脆爽可口味道鲜美的泡菜怎么腌制呢