在OkHttp3学习(一):基本使用中记录了怎么使用OkHttp
设置一个指定的请求,我们请求的参数有了,之后我们就是发起请求了。那么OkHttp3
又是怎么发起的这次请求呢?
先看下之前的一个GET
请求
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.get()
.url(PATH)
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
String string = response.body().string();
Log.i(TAG, "onResponse: "+string);
}
}
});
在这次请求中我们设置好Request
请求的相关参数之后,我们就调用了。client.newCall(request)
。从字面意思猜测这个newCall
就是在创建一次新的请求。
Call
Call
是一个接口,源码是这样的。(OkHttpClient
实现了Call.Factory
接口)
public interface Call extends Cloneable {
Request request(); //返回发起这个Call的原始Request
Response execute() throws IOException; //执行请求
void enqueue(Callback responseCallback); //在以后的某个时间点执行
void cancel(); //取消请求 如果请求已经成功了就不能取消了
boolean isExecuted(); //是否正在执行
boolean isCanceled(); //是否取消了
Call clone();
interface Factory {
Call newCall(Request request);
}
}
newCall
来看下client.newCall(request)
都干了些什么。
/**
* Prepares the {@code request} to be executed at some point in the future.
*/
@Override public Call newCall(Request request) {
return new RealCall(this, request, false /* for web socket */);
}
通过源码看到。在这里我们是创建了一个RealCall
的实例。之后我们又调用了RealCall
的enqueue()
。来看下。
@Override public Response execute() throws IOException {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
try {
client.dispatcher().executed(this);
Response result = getResponseWithInterceptorChain();
if (result == null) throw new IOException("Canceled");
return result;
} finally {
client.dispatcher().finished(this);
}
}
@Override public void enqueue(Callback responseCallback) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
进入方法,先判断是否执行了。之后调用了captureCallStackTrace()
,之后我们就看到了。这次请求是通过OkHttpClient
的Dispatcher
调度器执行的。(client.dispatcher()
返回OkHttp
的成员变量Dispatcher
)。我们看到enqueue()
和executed()
都是调用了Dispatcher
的方法。
/** Used by {@code Call#execute} to signal it is in-flight. */
synchronized void executed(RealCall call) {
runningSyncCalls.add(call);
}
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
在这部分代码中。runningAsyncCalls
异步请求的双端队列。 runningSyncCalls
同步请求的双端队列。
尽管RealCall
和AsyncCall
都叫做Call。但是还是有点区别的。AsyncCall
是Runnable
的间接子类并没有实现Call
接口或者集成Call
,而RealCall
则是一个Call
的子类。他们有着本质上的区别。
/** 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<>();
AcyncCall
在上面的代码中我们可以看到enqueue
在执行的时候是同过executorService()
来执行的。该方法会返回一个ExecutorService
,同事也初始化了Dispatcher
中的executorService
变量。
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;
}
Dispatcher
通过这个execurorService
来管理着所有异步请求(AcyncCall)。
同步请求是通过调用RealCall
的execute()
方法执行的,异步请求是通过AsyncCall
的execute
来执行的。
不过AsyncCall
的execute()
是在父类NamedRunnable
的run()
方法中调用的,也就是由线程池来管理着。
分析AsyncCall
和RealCall
的execute()
方法我们会看到,都会执行
finally {
client.dispatcher().finished(this);
}
都执行了Dispatcher
的finished()
函数,来看下:
/** Used by {@code AsyncCall#run} to signal completion. */
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 <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();
}
}
从双端队列中取出call,如果是AsyncCall
就执行promoteCalls()
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。