1.创建OkHttpClient
OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
OkHttp的创建采用了构建者模式,OkHttpClient.Builder()无参构造方法为 OkHttpClient的属性提供了默认值。
public Builder() {
dispatcher = new Dispatcher();
protocols = DEFAULT_PROTOCOLS;
connectionSpecs = DEFAULT_CONNECTION_SPECS;
eventListenerFactory = EventListener.factory(EventListener.NONE);
proxySelector = ProxySelector.getDefault();
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;
connectTimeout = 10_000;
readTimeout = 10_000;
writeTimeout = 10_000;
pingInterval = 0;
}
2.创建Request
Request request = new Request.Builder().url("https://www.baidu.com").get().build();
Request的创建也采用了构建者模式,Request的属性包括url、请求方法、请求头、请求体、标签,在Request.Builder()中为Request设置的默认请求方法是“GET”。
final HttpUrl url;
final String method;
final Headers headers;
final @Nullable RequestBody body;
final Object tag;
public Builder() {
this.method = "GET";
this.headers = new Headers.Builder();
}
3.创建Call
Call call = okHttpClient.newCall(request);
okHttpClient.newCall方法如下:
@Override
public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}
Call是一个接口,该接口提供了同步请求、异步请求、取消请求等方法,RealCall是其实现类,在RealCall的newRealCall方法中,通过传入OkHttpClient和Request对象创建了一个RealCall对象,
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;
}
4.同步请求
Response response = call.execute();
RealCall的execute方法如下:
@Override public Response execute() throws IOException {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
try {
client.dispatcher().executed(this);
Response result = getResponseWithInterceptorChain();
if (result == null) throw new IOException("Canceled");
return result;
} catch (IOException e) {
eventListener.callFailed(this, e);
throw e;
} finally {
client.dispatcher().finished(this);
}
}
首先判断请求有没有执行过,如果请求已经执行过,再次执行会抛出“Already Executed”异常。
client.dispatcher().executed(this)会将RealCall对象放入双端队列中。
private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();
synchronized void executed(RealCall call) {
runningSyncCalls.add(call);
}
getResponseWithInterceptorChain()方法如下:
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List<Interceptor> interceptors = new ArrayList<>();
//添加用户自定义拦截器
interceptors.addAll(client.interceptors());
//添加重试与重定向拦截器
interceptors.add(retryAndFollowUpInterceptor);
//添加桥拦截器
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, null, null, null, 0,
originalRequest, this, eventListener, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
//执行责任链
return chain.proceed(originalRequest);
}
getResponseWithInterceptorChain使用了责任链模式,将网络请求用到的多个拦截器形成一个链条,Request请求经过多个拦截器的处理返回Response对象。
无论请求是否成功,在finally中执行client.dispatcher().finished(this),将RealCall对象从双端队列中移除。
5.异步请求
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
System.out.println("请求失败: " + e.toString());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String string = response.body().string();
System.out.println("请求成功: " + string);
}
});
RealCall的enqueue方法如下:
@Override public void enqueue(Callback responseCallback) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
首先判断请求有没有执行过,然后把用户创建的回调封装到AsyncCall对象中,执行DisPatcher的enqueue方法,如下:
//异步请求准备队列
private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();
//异步请求执行队列
private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
maxRequests的值是64,代表同时请求的最大数量,maxRequestsPerHost的值是5,代表每个服务器的最大请求数量,当满足条件时,会将AsyncCall放到执行队列中,并使用线程池执行该请求,当不满足条件时,会将AsyncCall放到准备队列中。
executorService()创建了一个缓存线程池,当线程空闲时间小于1分钟时,如果提交新的任务,会进行线程的复用,如果线程空闲时间超过1分钟,线程会终止,如果此时提交新任务,线程池会创建新的线程来处理。
public synchronized ExecutorService executorService() {
if (executorService == null) {
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
}
return executorService;
}
AsyncCall的execute方法如下:
@Override protected void execute() {
boolean signalledCallback = false;
try {
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) {
if (signalledCallback) {
// 用户的回调中出现异常
Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
} else {
//OkHttp的请求出现异常
eventListener.callFailed(RealCall.this, e);
responseCallback.onFailure(RealCall.this, e);
}
} finally {
client.dispatcher().finished(this);
}
}
在AsyncCall的execute中依然使用了责任链模式进行请求。使用了signalledCallback标识用来区分异常来自用户的回调或OkHttp请求过程。
在finished方法中,除了移除准备队列的AsyncCall,还要把准备队列的AsyncCall移动到执行队列中。
private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
int runningCallsCount;
Runnable idleCallback;
synchronized (this) {
if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
if (promoteCalls) promoteCalls();
runningCallsCount = runningCallsCount();
idleCallback = this.idleCallback;
}
if (runningCallsCount == 0 && idleCallback != null) {
idleCallback.run();
}
}
private void promoteCalls() {
if (runningAsyncCalls.size() >= maxRequests) return; // Already running max capacity.
if (readyAsyncCalls.isEmpty()) return; // No ready calls to promote.
for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
AsyncCall call = i.next();
//把准备队列的AsyncCall移到执行队列中
if (runningCallsForHost(call) < maxRequestsPerHost) {
i.remove();
runningAsyncCalls.add(call);
executorService().execute(call);
}
if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity.
}
}