Okhttp的浅层架构分析
Okhttp的责任链模式和拦截器分析
Okhttp之RetryAndFollowUpInterceptor拦截器分析
Okhttp之BridgeInterceptor拦截器分析
Okhttp之CacheInterceptor拦截器分析
Okhttp之ConnectInterceptor拦截器分析
Okhttp之网络连接相关三大类RealConnection、ConnectionPool、StreamAllocation
Okhttp之CallServerInterceptor拦截器分析
浅析okio的架构和源码实现
Okhttp作为现在最受欢迎的网络框架,没有之一,为什么会这么有说服力的让开发者们都认可呢,带着这些疑问我们看看它的源码是怎么设计的。
首先看看okhttp的异步Get请求:
//bulider模式创建一个默认的OkhttpClient对象
var client = OkHttpClient.Builder().build()
//仍然是builder模式创建Request对象
var request = Request.Builder().url("https://www.baidu.com").get().build()
//调用OkHttpClient的newCall()方法新建了一个RealCall对象
val newCall = client.newCall(request)
//调用RealCall的enqueue()方法开启异步线程访问,传入回调接口
newCall.enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
}
override fun onResponse(call: Call, response: Response) {
}
})
我们就一步步跟着看看它每一个步骤都是怎么实现的,先看看OkHttpClient的主要代码,这里就只先关注以上步骤出现的相关代码,先把流程梳理清楚,所以就看看它的Builder内部类:
public static final class Builder {
Dispatcher dispatcher; //异步调用分配者,通过线程池,来分别调用
@Nullable Proxy proxy;
List protocols;
List connectionSpecs;
final List interceptors = new ArrayList<>();// 自定义拦截器 集合
final List networkInterceptors = new ArrayList<>(); //网络拦截器 集合
EventListener.Factory eventListenerFactory;
ProxySelector proxySelector;
CookieJar cookieJar; //cookie
@Nullable Cache cache; //缓存
@Nullable InternalCache internalCache;
SocketFactory socketFactory;
@Nullable SSLSocketFactory sslSocketFactory;
@Nullable CertificateChainCleaner certificateChainCleaner;
HostnameVerifier hostnameVerifier;
CertificatePinner certificatePinner;
Authenticator proxyAuthenticator;
Authenticator authenticator;
ConnectionPool connectionPool; //线程池,所有的有效链接都会保存在这里,也优先在这里查找是否有可用的链接
Dns dns;
boolean followSslRedirects;
boolean followRedirects;
boolean retryOnConnectionFailure;
//各种超时时间设置,看名字就知道是干啥的啦
int callTimeout;
int connectTimeout;
int readTimeout;
int writeTimeout;
int pingInterval;
public Builder() {
dispatcher = new Dispatcher();
protocols = DEFAULT_PROTOCOLS;
connectionSpecs = DEFAULT_CONNECTION_SPECS;
eventListenerFactory = EventListener.factory(EventListener.NONE);
proxySelector = ProxySelector.getDefault();
if (proxySelector == null) {
proxySelector = new NullProxySelector();
}
cookieJar = CookieJar.NO_COOKIES;
socketFactory = SocketFactory.getDefault();
hostnameVerifier = OkHostnameVerifier.INSTANCE;
certificatePinner = CertificatePinner.DEFAULT;
proxyAuthenticator = Authenticator.NONE;
authenticator = Authenticator.NONE;
connectionPool = new ConnectionPool();
dns = Dns.SYSTEM;
followSslRedirects = true;
followRedirects = true;
retryOnConnectionFailure = true;
callTimeout = 0;
connectTimeout = 10_000;
readTimeout = 10_000;
writeTimeout = 10_000;
pingInterval = 0;
}
...省略其他代码
}
主要的一些属性都注释了,其他的暂时不深究,这里默认初始化的时候重点关注Dispatcher类,到时候会用到它。接下来看看newCall()方法:
public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}
来看看RealCall类
final class RealCall implements Call {
final OkHttpClient client;
final RetryAndFollowUpInterceptor retryAndFollowUpInterceptor;
final AsyncTimeout timeout;
//静态方法,传入了client,request等参数
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;
}
@Override
public void enqueue(Callback responseCallback) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
//OkhttpClient里的那个成员变量dispatcher
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
}
我们知道okhttp的异步请求是调用了enqueue()方法,在这个方法里我们看到了之前提到的OkhttpClient里的那个成员变量dispatcher,最终是调用了它的enqueue()方法,那我们来看看Dispatcher的enqueue()方法:
public final class Dispatcher {
private int maxRequests = 64;
private int maxRequestsPerHost = 5;
private @Nullable Runnable idleCallback;
//熟悉的线程池
private @Nullable ExecutorService executorService;
//准备好的要执行的任务
private final Deque readyAsyncCalls = new ArrayDeque<>();
void enqueue(AsyncCall call) {
synchronized (this) {
readyAsyncCalls.add(call);
}
promoteAndExecute();
}
}
private boolean promoteAndExecute() {
assert (!Thread.holdsLock(this));
List executableCalls = new ArrayList<>();
boolean isRunning;
//准备可执行的任务
synchronized (this) {
for (Iterator i = readyAsyncCalls.iterator(); i.hasNext(); ) {
AsyncCall asyncCall = i.next();
if (runningAsyncCalls.size() >= maxRequests) break; // Max capacity.
if (runningCallsForHost(asyncCall) >= maxRequestsPerHost) continue; // Host max capacity.
i.remove();
executableCalls.add(asyncCall);
runningAsyncCalls.add(asyncCall);
}
isRunning = runningCallsCount() > 0;
}
//遍历执行可执行的任务
for (int i = 0, size = executableCalls.size(); i < size; i++) {
AsyncCall asyncCall = executableCalls.get(i);
//放到线程池里去执行,这个executeOn()是asyncCall的方法,executorService()方法就是得到一个线程池,AsyncCall类,这个类肯定是个ruannable
asyncCall.executeOn(executorService());
}
return isRunning;
}
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;
}
AsyncCall类,前面提到这个类肯定是个ruannable,看看源码:
//带名称的Runnable ,方便管理标记,AsyncCall继承了这个类
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();
}
//AsyncCall,实现的了NamedRunnable
final class AsyncCall extends NamedRunnable {
private final Callback responseCallback;
AsyncCall(Callback responseCallback) {
super("OkHttp %s", redactedUrl());
this.responseCallback = responseCallback;
}
//上面dispatcher调用的方法
void executeOn(ExecutorService executorService) {
assert (!Thread.holdsLock(client.dispatcher()));
boolean success = false;
try {
//最终的执行步骤,线程池的execute()方法,注意executorService是执行了AsyncCall ,也就是会执行下面的execute() 方法,不要晕
executorService.execute(this);
success = true;
} catch (RejectedExecutionException e) {
InterruptedIOException ioException = new InterruptedIOException("executor rejected");
ioException.initCause(e);
eventListener.callFailed(RealCall.this, ioException);
responseCallback.onFailure(RealCall.this, ioException);
} finally {
if (!success) {
client.dispatcher().finished(this); // This call is no longer running!
}
}
}
//最终的请求提交,可以看到getResponseWithInterceptorChain()方法拿到response ,这就是开始了责任链调用模式,后面详细分析
@Override
protected void execute() {
boolean signalledCallback = false;
timeout.enter();
try {
//开启责任链调用拿到response
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) {
e = timeoutExit(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);
}
}
}
至此,okhttp的大致异步调用的大概结构了解了,说到底还是把请求任务封装成runnable放在线程池里去执行,当然这只是整体脉络,要继续了解它是怎么得到response响应的,就要开始聊聊它著名的责任链模式和拦截器的设计了,篇幅有限我们放到下篇来讲。