这里以非Kotlin版本介绍java
build.gradle
中添加组件:implementation 'com.squareup.okhttp3:okhttp:3.14.2'
复制代码
//注意这里,通常咱们用单例,Okhttp官方描述若是不用单例,线程管理等都失效了,浪费开销
/*Http performs best when you create a single {@code OkHttpClient} instance and reuse it for * all of your HTTP calls. This is because each client holds its own connection pool and thread * pools. Reusing connections and threads reduces latency and saves memory. Conversely, creating a * client for each request wastes resources on idle pools. */
OkHttpClient client = new OkHttpClient();
String run(String url) throws IOException {
Request request = new Request.Builder()
.url(url)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
复制代码
经过okhttp源码分析,直接建立的 OkHttpClient对象而且默认构造builder对象进行初始化web
public class OkHttpClient implements Cloneable, Call.Factory, WebSocket.Factory {
public OkHttpClient() {
this(new Builder());
}
OkHttpClient(Builder builder) {
this.dispatcher = builder.dispatcher;
this.proxy = builder.proxy;
this.protocols = builder.protocols;
this.connectionSpecs = builder.connectionSpecs;
this.interceptors = Util.immutableList(builder.interceptors);
this.networkInterceptors = Util.immutableList(builder.networkInterceptors);
this.eventListenerFactory = builder.eventListenerFactory;
this.proxySelector = builder.proxySelector;
this.cookieJar = builder.cookieJar;
this.cache = builder.cache;
this.internalCache = builder.internalCache;
this.socketFactory = builder.socketFactory;
...
this.hostnameVerifier = builder.hostnameVerifier;
this.certificatePinner = builder.certificatePinner.withCertificateChainCleaner(
certificateChainCleaner);
this.proxyAuthenticator = builder.proxyAuthenticator;
this.authenticator = builder.authenticator;
this.connectionPool = builder.connectionPool;
this.dns = builder.dns;
this.followSslRedirects = builder.followSslRedirects;
this.followRedirects = builder.followRedirects;
this.retryOnConnectionFailure = builder.retryOnConnectionFailure;
this.connectTimeout = builder.connectTimeout;
this.readTimeout = builder.readTimeout;
this.writeTimeout = builder.writeTimeout;
this.pingInterval = builder.pingInterval;
}
}
复制代码
通常以下:设计模式
Request request = new Request.Builder().url("url").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 {
}
});
复制代码
初始化构建者模式和请求对象,而且用URL替换Web套接字URL。缓存
public final class Request {
public Builder() {
this.method = "GET";
this.headers = new Headers.Builder();
}
public Builder url(String url) {
......
// Silently replace web socket URLs with HTTP URLs.
if (url.regionMatches(true, 0, "ws:", 0, 3)) {
url = "http:" + url.substring(3);
} else if (url.regionMatches(true, 0, "wss:", 0, 4)) {
url = "https:" + url.substring(4);
}
HttpUrl parsed = HttpUrl.parse(url);
......
return url(parsed);
}
public Request build() {
......
return new Request(this);
}
}
复制代码
主里主要是调用了newCall
方法,咱们跟进去看看:cookie
public class OkHttpClient implements Cloneable, Call.Factory, WebSocket.Factory {
@Override
public Call newCall(Request request) {
return new RealCall(this, request, false /* for web socket */);
}
}
复制代码
发现去new RealCall
了,咱们跟到RealCall
看看:网络
private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
this.client = client;
this.originalRequest = originalRequest;
this.forWebSocket = forWebSocket;
}
复制代码
能够看到只是初始化一些成员变量,真正的调用是RealCall
里面的enqueue(添加到队列)/execute(当即执行)
方法,咱们看看:架构
void enqueue(AsyncCall call) {
synchronized (this) {
/** Ready async calls in the order they'll be run. */
//private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();
// readyAsyncCalls是一个双端队列,把该call加入到准备的队列里
readyAsyncCalls.add(call);
// Mutate the AsyncCall so that it shares the AtomicInteger of an existing running call to
// the same host.
if (!call.get().forWebSocket) {
AsyncCall existingCall = findExistingCallWithHost(call.host());
if (existingCall != null) call.reuseCallsPerHostFrom(existingCall);
}
}
promoteAndExecute();
}
复制代码
上面不难发现最终调用了promoteAndExecute()
,咱们跟进去看看:socket
/** * Promotes eligible calls from {@link #readyAsyncCalls} to {@link #runningAsyncCalls} and runs * them on the executor service. Must not be called with synchronization because executing calls * can call into user code. * * @return true if the dispatcher is currently running calls. */
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();
if (runningAsyncCalls.size() >= maxRequests) break; // Max capacity. // 最大的线程请求的时候,再也不添加, maxRequests默认值是:64
if (asyncCall.callsPerHost().get() >= maxRequestsPerHost) continue; // Host max capacity. // 最大的DNS解析为:5
i.remove();
asyncCall.callsPerHost().incrementAndGet();
executableCalls.add(asyncCall);
runningAsyncCalls.add(asyncCall);
}
isRunning = runningCallsCount() > 0;
}
// 循环执行
for (int i = 0, size = executableCalls.size(); i < size; i++) {
AsyncCall asyncCall = executableCalls.get(i);
asyncCall.executeOn(executorService());
}
return isRunning;
}
复制代码
有一个问题,enqueue
是拿到Reponse的? 它和execute
区别?async
带着问题,咱们能够在RealCall
中能够发现 final class AsyncCall extends NamedRunnable
ide
这个NamedRunnable
是什么?
/** * Runnable implementation which always sets its thread name. */
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();
}
复制代码
根据源码发现它原来是一个runable
,而且抽象了execute
,因此execute
就是enqueue
去执行的核心方法,那么我就能够看到execute
方法的实现:
@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);
}
} finally {
client.dispatcher().finished(this);
}
}
复制代码
实际上跟execute
方法同样,都是调用了getResponseWithInterceptorChain
,跟进去看看:
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List<Interceptor> interceptors = new ArrayList<>();
interceptors.addAll(client.interceptors());// 1.添加自定义的拦截器
interceptors.add(new RetryAndFollowUpInterceptor(client));// 2.重试拦截
interceptors.add(new BridgeInterceptor(client.cookieJar())); // 3.Build一个适配的Request
interceptors.add(new CacheInterceptor(client.internalCache()));// 4.添加缓存拦截器
interceptors.add(new ConnectInterceptor(client)); // 5.ConnectInterceptor验证Get请求
if (!forWebSocket) {
interceptors.addAll(client.networkInterceptors()); // 6.非Websocket下建立的自定义网络拦截器
}
interceptors.add(new CallServerInterceptor(forWebSocket)); // 7. 真实的IO访问,使用了OKIO库去实现的
Interceptor.Chain chain = new RealInterceptorChain(interceptors, transmitter, null, 0,
originalRequest, this, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
.....
return response;
}
复制代码
从上面的设计模式能够看出来OKHttp使用了责任链
的设计模式. 至此流程已经完毕. 下面学习一些优秀的细节.