首先使用Okhttp发起一个异步请求,以此先简单分析OkHttp的大致流程。
okHttp使用:
OkHttpClient client=new OkHttpClient();
Request request=new Request.Builder()
.url("http://www.baidu.com")
.build();
Call call=client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});
Okhttp流程主要类 功能
OkHttpClient
使用建造者模式初始化连接池,Dispatcher等,为了节约资源推荐使用单列模式创建OkhttpClient对象,维护线程池比较耗资源。
Request
Http请求所需的URL,请求方法等,HTTP请求格式见上一章OkHttp3源码解析(一)Scoket实现HTTP请求。
RealCall
实现Call接口。
1. 同步
直接调用RealCall
的execute()
方法。通过拦截器链对Request进行封装,发起请求,对得到的Response进行封装,最后返回。拦截器链下章讲。
2. 异步
调用enqueue()
,最后会用调用Dispatcher的enqueue()
。传入的是一个Runable的子类AsyncCall(RealCall内部类)
@Override public void enqueue(Callback responseCallback) {
synchronized (this) {
//一个Call只能执行一次请求,不管是同步还是异步的。
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
transmitter.callStart();
//调用Dispatcher的enqueue方法
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
Dispatcher
包含线程池
public synchronized ExecutorService executorService() {
if (executorService == null) {
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue<>(), Util.threadFactory("OkHttp Dispatcher", false));
}
return executorService;
}
经过RealCallenqueue()
,来到了最后的Dispatcher的enqueue()
void enqueue(AsyncCall call) {
synchronized (this) {
//直接添加到准备队列,不同于以往的判断添加,
readyAsyncCalls.add(call);
if (!call.get().forWebSocket) {
AsyncCall existingCall = findExistingCallWithHost(call.host());
if (existingCall != null) call.reuseCallsPerHostFrom(existingCall);
}
}
promoteAndExecute();
}
后面执行promoteAndExecute();
遍历等待请求序列。
判断正在执行的请求数是否,小于64,并且同时请求的主机数小于5,不满足条件,直接Break停止当前遍历。
符合判断,则将当前等待执行请求加入临时可以执行序列executableCalls
,并且将当前请求添加到正在请求序列。继续遍历,知道遍历完所有等待请求序列或者是正在执行序列,主机数超过上限。
遍历可以执行序列,放入线程池执行请求。
private boolean promoteAndExecute() {
assert (!Thread.holdsLock(this));
List<AsyncCall> executableCalls = new ArrayList<>();
boolean isRunning;
synchronized (this) {
for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
AsyncCall asyncCall = i.next();
//判断正在执行请求数是否大于64,连接主机数大于5.不符合条件直接Break;
if (runningAsyncCalls.size() >= maxRequests) break; // Max capacity.
if (asyncCall.callsPerHost().get() >= maxRequestsPerHost) continue; // Host max capacity.
i.remove();
asyncCall.callsPerHost().incrementAndGet();
//符合要求,添加到可以执行List中
executableCalls.add(asyncCall);
//添加到正在执行List
runningAsyncCalls.add(asyncCall);
}
isRunning = runningCallsCount() > 0;
}
//可以执行List中有任务,放入线程池执行。
for (int i = 0, size = executableCalls.size(); i < size; i++) {
AsyncCall asyncCall = executableCalls.get(i);
asyncCall.executeOn(executorService());
}
return isRunning;
}
NamedRunnable
NamedRunnable
实现Runable接口,并包含抽象方法execute
。并在run方法中执行execute()
NamedRunnable主要代码。
@Override
public void run() {
exexute();
}
abstract void exexute();
AsyncCall
RealCall内部类,继承抽象类NamedRunnable,
实现抽象方法execute()
,当DIspatcher调用线程池执行请求,最终会到AsyncCall的execute()
。通过拦截器链处理得到Response,下章讲。
@Override protected void execute() {
try {
//拦截器链处理
Response response = getResponseWithInterceptorChain();
//成功,回调CallBack
responseCallback.onResponse(RealCall.this, response);
} catch (IOException e) {
//失败,回调CallBack
responseCallback.onFailure(RealCall.this, e);
} finally {
//请求结束,一些列处理,包括从正在执行系列中移除等操作。
client.dispatcher().finished(this);
}
}