版本是3.14.9
同步请求
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder().url("http://wwww.baidu.com").build();
Call call = okHttpClient.newCall(request);
try {
Response response = call.execute();
Log.d(TAG, "Response: " + response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
同步请求分析
- 创建OkHttpClient对象,
public class OkHttpClient implements Cloneable, Call.Factory, WebSocket.Factory {
public OkHttpClient() {
this(new Builder());
}
public static final class Builder {
Dispatcher dispatcher;
public Builder() {
// 创建Dispatcher对象
dispatcher = new Dispatcher();
}
}
}
- 创建Request对象
public final class Request {
public static class Builder {
public Builder() {
this.method = "GET";
this.headers = new Headers.Builder();
}
public Builder url(HttpUrl url) {
if (url == null) throw new NullPointerException("url == null");
this.url = url;
return this;
}
public Request build() {
if (url == null) throw new IllegalStateException("url == null");
// build()之后返回Request
return new Request(this);
}
}
}
okHttpClient.newCall(request)
创建RealCall对象
// 创建RealCall对象, RealCall中的内部类AsyncCall其实是Runnable对象
@Override public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}
RealCall.execute()
执行请求
// RealCall.java
final class RealCall implements Call {
// 执行同步请求
@Override public Response execute() throws IOException {
synchronized (this) {
// executed 每个RealCall只能请求一次网络
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
...
try {
// 将RealCall加入到同步请求的队列中
client.dispatcher().executed(this);
// 从拦截链获取响应, 异步最终也会走到这个方法,现在再分析异步.
return getResponseWithInterceptorChain();
} finally {
client.dispatcher().finished(this);
}
}
}
// Dispatcher.java
public final class Dispatcher {
// 准备好,还未请求
private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();
// 正在运行的请求
private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();
// 同步请求
private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();
// 将RealCall对象加入到同步请求队列中
synchronized void executed(RealCall call) {
runningSyncCalls.add(call);
}
}
异步请求
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder().url("http://wwww.baidu.com").build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d(TAG, "onFailure: ");
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d(TAG, "Response: " + response.body().string());
}
});
异步请求分析
OkHttpClient
,Request
,RealCall
对象的创建与同步无异,区别在RealCall.execute()
与’RealCall.enqueue()’
final class RealCall implements Call {
@Override public void enqueue(Callback responseCallback) {
...
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
// 类型最终为Runnable
final class AsyncCall extends NamedRunnable {
void executeOn(ExecutorService executorService) {
assert (!Thread.holdsLock(client.dispatcher()));
boolean success = false;
try {
// 通过线程池执行当前的AsyncCall,也就是Runnable对象中的run()
// NamedRunnable类中的run()方法最终调用execute(),该方法具体由AsyncCall实现.
executorService.execute(this);
success = true;
}
...
}
// run()方法的最终实现
@Override protected void execute() {
boolean signalledCallback = false;
transmitter.timeoutEnter();
try {
// 调用拦截器链获取Response
Response response = getResponseWithInterceptorChain();
signalledCallback = true;
// Callback()中的回调方法
responseCallback.onResponse(RealCall.this, response);
} catch (IOException e) {
...
} catch (Throwable t) {
cancel();
if (!signalledCallback) {
...
canceledException.addSuppressed(t);
// Callback()中的回调方法
responseCallback.onFailure(RealCall.this, canceledException);
}
throw t;
} finally {
client.dispatcher().finished(this);
}
}
}
}
public final class Dispatcher {
private int maxRequests = 64;
private int maxRequestsPerHost = 5;
// 准备好,还未请求
private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();
// 正在运行的请求
private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();
// 同步请求
private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();
// 将RealCall对象加入到同步请求队列中
synchronized void executed(RealCall call) {
runningSyncCalls.add(call);
}
void enqueue(AsyncCall call) {
// 将AsyncCall对象加入异步请求准备队列中
readyAsyncCalls.add(call);
...
//
promoteAndExecute();
}
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.
if (asyncCall.callsPerHost().get() >= maxRequestsPerHost) continue; // Host max capacity.
i.remove();
asyncCall.callsPerHost().incrementAndGet();
// 将等待队列中的AsyncCall 加入到正在异步请求的队列中
executableCalls.add(asyncCall);
runningAsyncCalls.add(asyncCall);
}
isRunning = runningCallsCount() > 0;
}
for (int i = 0, size = executableCalls.size(); i < size; i++) {
// 从集合中取出AsyncCall
AsyncCall asyncCall = executableCalls.get(i);
// 调用AsyncCall中的executeOn()方法,executorService()返回一个线程池
asyncCall.executeOn(executorService());
}
return isRunning;
}
// 获取一个线程池
public synchronized ExecutorService executorService() {
if (executorService == null) {
// 核心池大小为0,空闲线程最多等待60s收回
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue<>(), Util.threadFactory("OkHttp Dispatcher", false));
}
return executorService;
}
}
getResponseWithInterceptorChain()
final class RealCall implements Call {
final class AsyncCall extends NamedRunnable {
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List<Interceptor> interceptors = new ArrayList<>();
// OkHttpClient中自己自定义的一些Interceptor
interceptors.addAll(client.interceptors());
// 错误、重定向拦截器
interceptors.add(new RetryAndFollowUpInterceptor(client));
// 桥接拦截器,桥接应用层与网络层,添加必要的头、
interceptors.add(new BridgeInterceptor(client.cookieJar()));
// 缓存处理,Last-Modified、ETag、DiskLruCache等
interceptors.add(new CacheInterceptor(client.internalCache()));
// 连接拦截器
interceptors.add(new ConnectInterceptor(client));
if (!forWebSocket) {
// 网络请求拦截器只对非网页请求生效
interceptors.addAll(client.networkInterceptors());
}
// 真正访问服务器的拦截器
interceptors.add(new CallServerInterceptor(forWebSocket));
// 创建RealInterceptorChain对象, 注意此时的index为0
Interceptor.Chain chain = new RealInterceptorChain(interceptors, transmitter, null, 0,
originalRequest, this, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
boolean calledNoMoreExchanges = false;
try {
// 调用RealInterceptorChain.proceed() 接收参数是Request
Response response = chain.proceed(originalRequest);
...
return response;
}
...
}
}
}
RealInterceptorChain.proceed(originalRequest)
public final class RealInterceptorChain implements Interceptor.Chain {
public Response proceed(Request request, Transmitter transmitter, @Nullable Exchange exchange)
throws IOException {
...
// 注意此时的index为index+1,回想之前的一步,创建RealInterceptorChain时候, index是为0.
// 可以看出来这里用的是责任链设计模式.
// 拦截器链最后就是一个递归调用, 最后调用到 CallServerInterceptor才开始真正的请求网络,然后再一步步将请求到的数据从拦截器返回来.
RealInterceptorChain next = new RealInterceptorChain(interceptors, transmitter, exchange,
index + 1, request, call, connectTimeout, readTimeout, writeTimeout);
// 上一步中index为0,那么这个 Interceptor 类型就是错误重定向拦截器
Interceptor interceptor = interceptors.get(index);
// 这里的next还是RealInterceptorChain对象. 下面看下错误重定向请求拦截器
Response response = interceptor.intercept(next);
...
return response;
}
}
RetryAndFollowUpInterceptor.intercept(next)
public final class RetryAndFollowUpInterceptor implements Interceptor {
@Override public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
RealInterceptorChain realChain = (RealInterceptorChain) chain;
...
try {
// 这样一个循环最后又回到了RealInterceptorChain中的proceed()方法中了,此时的RealInterceptorChain中属性index为1.
// 这样一个循环就会将所有的 Interceptor都调用到.
response = realChain.proceed(request, transmitter, null);
success = true;
}
...
}
}
总结
OkHttp的底层是通过Java的Socket发送HTTP请求与接受响应的,OkHttp实现了连接池的概念,即对于同一主机的多个请求,其实可以共用一个Socket连接,而不是每次发送完 HTTP请求就关闭底层的Socket,这样就实现了连接池的概念。而OkHttp对Socket的读写操作使用的OkIo库进行了一 层封装。