OkHttp 源码分析
基于OkHttp3.11.0
implementation("com.squareup.okhttp3:okhttp:3.11.0")
网络框架的核心思想都是构建基本的执行单元之后(1),根据任务类型放入对应的任务队列里(2),再由线程池去执行(3)。OKHttp也不列外。
初始化OKHttpClient
OKHttpclient采用了Builder模式创建
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(5, TimeUnit.SECONDS)
.writeTimeout(5, TimeUnit.SECONDS)
.build();
构建执行单元
1:GET请求
Request request = new Request.Builder().url("www.baidu.com")
.get() // 默认就是get请求
.build();
2: POST请求
POST与GET多了一个body。
FormBody body = new FormBody.Builder()
.add("key", "value")
.add("key1", "value1")
.build();
Request post = new Request.Builder().url("www.baidu.com")
.post(body)
.build();
执行
1:同步执行
try {
Response response = okHttpClient.newCall(post).execute();
if (response.code() == 200){
}
} catch (IOException e) {
}
然后就可以根据response的结果操作了。
2:异步执行
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});
在对应的回调函数里做对应的业务逻辑。
以上就是OKHttp的使用的基本使用。
这里Request就是请求单元,不论是同步执行还是异步执行,都调用okHttpClient.newCall(request) 生成了一个RealCall对象,然后分别调用该对象的execute(同步执行)方法或者enqueue(异步执行)方法。
@Override public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}
OKHttp的newCall方法调用RealCall的静态方法newRealCall().
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;
}
private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
this.client = client;
this.originalRequest = originalRequest;
this.forWebSocket = forWebSocket;
this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket);
}
可以看到,newRealCall方法将client作为自己构造函数的参数传入
下面这个方法是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);
}
}
可以看到调用了 client.dispatcher().executed(this);
最中调用 Response result = getResponseWithInterceptorChain();并返回Result对象
如果发生了异常则调用 eventListener.callFailed(this, e);
而最终这会调用 client.dispatcher().finished(this),来结束这个call。
这里面有一个很重要的类Dispatcher,它是OKHttpclient的一个内部成员,同时OKHttpclient是request的内部成员
public final class Dispatcher {
private int maxRequests = 64; //最大的请求数量
private int maxRequestsPerHost = 5; //同义主机同时支持的最大请求数
private @Nullable Runnable idleCallback;
/** Executes calls. Created lazily. */
private @Nullable ExecutorService executorService;
/** Ready async calls in the order they'll be run. */
private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();//准备执行的异步任务队列
/** Running asynchronous calls. Includes canceled calls that haven't finished yet. */
private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>(); //正在执行的异步任务队列
/** Running synchronous calls. Includes canceled calls that haven't finished yet. */
private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>(); //正在运行的同步任务队列
}
分别看到,这个类的同步执行方法是
synchronized void executed(RealCall call) {
runningSyncCalls.add(call);
}
将改call假如同步执行队列中。
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
异步执行方法是先进行判断,只有正在执行的异步任务队列长度小于了最大的请求数并且改请求的主机的正在请求数量小于每个主句的同时的最大连接数世才将改请求加入到正在执行的异步任务队列里,然后由具体的执行任务来执行这个请求任务。
不然就把这个任务加入到待执行的异步执行队队列。
这里RealCall 对象突然就变成了一个AsyncCall对象
@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));
}
在RealCall执行enqueue方法时将一个回调对象作为构造参数生成了一个AsyncCall对象,传入了Dispatcher的enqueue方法。
final class AsyncCall extends NamedRunnable {
private final Callback responseCallback;
AsyncCall(Callback responseCallback) {
super("OkHttp %s", redactedUrl());
this.responseCallback = responseCallback;
}
}
Async对象其实继承了NamedRunnable。而NamedRunnable实现了Runnable接口,可以看出其实Async其实就是一个命名后的runnable对象。
这里把RealCall同步执行和异步执行的代码列出来
1:同步执行
@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);
}
}
2:异步执行
最终调用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) {
// 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);
}
}
}
可以看出不管是同步执行还是异步执行,最终都是调用getResponseWithInterceptorChain();
方法得出Response
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);
}
在这个方法里首先将用户添加到OKHttpClient上的应用拦截器添加到拦截器列表里。然后一次添加重试重定向拦截器, 头部信息处理拦截器,缓存拦截器, 连接拦截器,然后再加上OKhttpclient配置的网络拦截器,最后添加最终发起请求的拦截器。
拦截器这里使用了不完整的责任链模式,依次处理返回的response,最后返回最终的response。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。