1、OkHttp恳求整体流程是怎样的
- 构建
OkhttpClient
目标 - 构建
Request
目标 - Request传入到
newCall办法
生成Realcall
目标,用它来建议新恳求 -
分发器
维护恳求行列和线程池,完结恳求调配- 同步-》realcall中的execute办法,client.dispatcher().executed(this);履行runningSyncCalls.add(call); 再履行getResponseWithInterceptorChain
- 异步-》realcall中的enqueue办法,client.dispatcher().enqueue(new AsyncCall(responseCallback));分发器中加到异步恳求行列。再线程池恳求,终究调用到getResponseWithInterceptorChain
- 履行
getResponseWithInterceptorChain
跑到阻拦器
- 履行chain.proceed(originalRequest)回来成果
Response
2、分发器是怎么作业的?
2.1 同步
-
Realcall.execute() 会跑到分发器Dispatcher.java 履行execute()
-
加到runningSyncCalls也就是同步线程行列中
-
调用getResponseWithInterceptorChain()运行阻拦器用的责任链形式,
终究回来Response
-
用完移除RealCall 调用client.dispatcher().finished(this);
-------------Realcall.java
@Override public Response execute() throws IOException {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
transmitter.timeoutEnter();
transmitter.callStart();
try {
//1、 分发器履行execute 传入
client.dispatcher().executed(this);
// 2、履行getResponseWithInterceptorChain()
return getResponseWithInterceptorChain();
} finally {
//3、用完移除RealCall
client.dispatcher().finished(this);
}
}
-------------Dispatcher.java
synchronized void executed(RealCall call) {
runningSyncCalls.add(call);
}
2.2 异步
2.2.1 异步履行流程
- Realcall.enqueue(new AsyncCall())
- 恳求数不超过64,且同一host恳求不能超过5个。
- 加入到runningAsyncCalls
- 加入到线程池中中履行,executorService().execute(call);
- 每个使命完结后,都会调用分发器的
finished
办法,这儿面会取出等候行列readyAsyncCalls中的使命继续履行
- 否则加入到等候行列readyAsyncCalls中
-------------Dispatcher.java
synchronized void enqueue(AsyncCall call) {
//恳求数最大不超过64,同一Host恳求不能超过5个
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
2.2.2 异步AysncCall类剖析
- AysncCall承继了抽象类NamedRunnable,线程池终究会跑AysncCall的run办法,履行到了AysncCall的execute办法,跑到
getResponseWithInterceptorChain()
;
final class AsyncCall extends NamedRunnable {
private final Callback responseCallback;
private volatile AtomicInteger callsPerHost = new AtomicInteger(0);
AsyncCall(Callback responseCallback) {
super("OkHttp %s", redactedUrl());
this.responseCallback = responseCallback;
}
...
@Override protected void execute() {
boolean signalledCallback = false;
transmitter.timeoutEnter();
try {
Response response = getResponseWithInterceptorChain();
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 {
responseCallback.onFailure(RealCall.this, e);
}
} catch (Throwable t) {
cancel();
if (!signalledCallback) {
IOException canceledException = new IOException("canceled due to " + t);
canceledException.addSuppressed(t);
responseCallback.onFailure(RealCall.this, canceledException);
}
throw t;
} finally {
client.dispatcher().finished(this);
}
}
}
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();
}
3、阻拦器怎么作业?
-
责任链设计是 将
恳求者
与履行者
进行解耦
,恳求发了,不用关怀细节。这个链上的每一个节点都有机会处理恳求,处理完了交给下一个,呈一个U形结构。如下图所示。CallServerInterceptor
的intercept
办法,此办法会将网络呼应的成果封装成一个Response
目标并return
-
- 应用阻拦器(用户可自定义)
- 拿到最原始恳求,能够添加自定义header、通用参数等
- 重试重定向阻拦器
- 处理过错重试和重定向
- 桥接阻拦器
- 应用层和网络层的桥接阻拦器,主要作业是条件cookie、固定和header,保存成果的cookie,如呼应用过gzip压缩过,就还需要解压
- 缓存阻拦器
- 假如命中缓存则不会建议网络恳求
- 衔接阻拦器
- 内部维护一个衔接池,负责衔接服用、创立衔接(3次握手)、释放衔接以及创立衔接上的socket流
- 网络阻拦器(用户可自定义)
- 通常用于检测网络层的数据衔接
- 恳求服务阻拦器
- 前置准备作业完结后,真正建议网络恳求
- 应用阻拦器(用户可自定义)
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List<Interceptor> interceptors = new ArrayList<>();
interceptors.addAll(client.interceptors());
interceptors.add(new RetryAndFollowUpInterceptor(client));
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, transmitter, null, 0,
originalRequest, this, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
boolean calledNoMoreExchanges = false;
try {
Response response = chain.proceed(originalRequest);
if (transmitter.isCanceled()) {
closeQuietly(response);
throw new IOException("Canceled");
}
return response;
} catch (IOException e) {
calledNoMoreExchanges = true;
throw transmitter.noMoreExchanges(e);
} finally {
if (!calledNoMoreExchanges) {
transmitter.noMoreExchanges(null);
}
}
}