1、 调用示例
同步方式:
new Thread(new Runnable() {
@Override
public void run() {
try {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url("http://www.baidu.com").build();
Response response = client.newCall(request).execute();
Log.d(TAG, "response sync:" + response.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
通过追溯源码,流程图如下:
image
异步方式:
try {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url("http://www.baidu.com").build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Request request, IOException e) {
}
@Override
public void onResponse(Response response) throws IOException {
Log.d(TAG, "response async:" + response.toString());
}
});
} catch (Exception e) {
e.printStackTrace();
}
通过追溯源码,流程图如下:
image
分析
同步和异步请求的核心方法都是getResponseWithInterceptorChain(),需要注意的是,同步方法没有在工作线程干活,而异步方法是在线程池里面执行,Android不允许在主线程里面做网络请求操作,如果同步请求的话,还必须在非主线程中。
异步方式请求是执行enqueue方法,有两个列表维护执行状态,runningAsyncCalls和readyAsyncCalls,分别是正在执行和等待执行列表,而同步方式则是直接提交请求。异步请求当一次AsyncCall执行完毕之后,在Dispatcher的promoteCalls方法会做两个状态列表的切换,等待列表切换到正在执行列表,同时删除等待列表中最前面的Call。如下:
private void promoteCalls() {
if (runningAsyncCalls.size() >= maxRequests) return; // Already running max capacity.
if (readyAsyncCalls.isEmpty()) return; // No ready calls to promote.
for (Iterator i = readyAsyncCalls.iterator(); i.hasNext(); ) {
AsyncCall call = i.next();
if (runningCallsForHost(call) < maxRequestsPerHost) {
i.remove();
runningAsyncCalls.add(call);
executorService().execute(call);
}
if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity.
}
}
遍历readyAsyncCalls列表里面的call,如果正在运行并小于最大的请求数,就可以加到runningAsyncCalls中了,然后接下来execute执行这个请求。
而promoteCalls方法是被Dispatcher的finished方法执行。RealCall中同步或异步execute方法执行完毕后会在finally中执行client.dispatcher().finished(this)方法,如下:
void finished(AsyncCall call) {
finished(runningAsyncCalls, call, true);
}
/** Used by {@code Call#execute} to signal completion. */
void finished(RealCall call) {
finished(runningSyncCalls, call, false);
}
private void finished(Deque 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();
}
}
第一个是finished异步请求完成之后调用,第二finished是同步请求完成之后调用,最终都会调用到带泛型参数的finished,并将执行完的call从runningAsyncCalls(异步)或runningSyncCalls(同步)中删除。promoteCalls参数用来区分是否是异步请求,如果是的话,执行promoteCalls方法。
文章将同步至微信公众号:Android部落格