本次阅读的okhttp源码版本为3.7.0
我读源码的习惯是从入口开始看起,所以我们首先看看一次使用okhttp请求的代码流程
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.get()
.url("http://www.baidu.com")
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {}
@Override
public void onResponse(Call call, Response response) throws IOException {}
});
可以看到,一次请求最小元素是newCall()里面的Call。
可以看到Call只是一个接口而已;需要注意的点已经标红了
- 一个Call,它不能被执行两次(即enqueue或execute只能调用一次)
- 一个Call可以取消,但不是一定能取消,假如请求已完成就不能取消了
具体是为什么继续往下看。
在源码里面可以看到RealCall是继承Call,那么来看一下RealCall的实现
可以看到每次进行 execute 或 enqueue 的时候都会上锁然后通过判断是否执行过该 Call 故重复调用会抛出异常。
那么接下来我们先看 execute (同步请求),在代码中可以看到首先执行了
client.dispatcher().executed(call)
这个方法,在最后执行了client.dispatcher().finished(this);
这个方法,那Dispatcher是什么?Dispatcher是okhttp中的调度器,请求的执行政策
client.dispatcher().executed(call)
这个方法比较简单,只是单纯的往同步请求队列添加而已
这里如果是同步就是简单的往同步请求队列移除
接着我们来看最关键的 getResponseWithInterceptorChain()
在其中,这个index起到至关重要的作用。
所以由上图我们得知最后会优先执行了拦截器链最后的一个拦截器(即上方的CallServerInterceptor拦截器,这个拦截器会进行真正的网络请求),然后再一层层将结果返回给各个拦截器处理。
最后我们再看看异步请求,执行了client.dispatcher().enqueue(new AsyncCall(responseCallback));
client.dispatcher().executed(call)
这个方法比较简单,首先判断正在运行的请求数是否小于设置值(默认值)且与该请求相同主机的请求是否小于设置值(默认值),是则加入线程池中并添加进正在请求的队列;否则加入待请求的队列。那看看传进去的AsyncCall
可以看到基本和同步请求几乎是一样的,相当于把同步请求放进runnable里面然后多了回调,。
好了,本次阅读到此告一段落