OkHttp3学习(二):发送一个请求

OkHttp3学习(一):基本使用中记录了怎么使用OkHttp设置一个指定的请求,我们请求的参数有了,之后我们就是发起请求了。那么OkHttp3又是怎么发起的这次请求呢?

先看下之前的一个GET请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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接口)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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)都干了些什么。

1
2
3
4
5
6
/**
* 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的实例。之后我们又调用了RealCallenqueue()。来看下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@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(),之后我们就看到了。这次请求是通过OkHttpClientDispatcher调度器执行的。(client.dispatcher()返回OkHttp的成员变量Dispatcher)。我们看到enqueue()executed()都是调用了Dispatcher的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
/** 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同步请求的双端队列。
尽管RealCallAsyncCall都叫做Call。但是还是有点区别的。AsyncCallRunnable的间接子类并没有实现Call接口或者集成Call,而RealCall则是一个Call的子类。他们有着本质上的区别。

1
2
3
4
5
/** 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变量。

1
2
3
4
5
6
7
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)。
同步请求是通过调用RealCallexecute()方法执行的,异步请求是通过AsyncCallexecute来执行的。
不过AsyncCallexecute()是在父类NamedRunnablerun()方法中调用的,也就是由线程池来管理着。
分析AsyncCallRealCallexecute()方法我们会看到,都会执行

1
2
3
finally {
client.dispatcher().finished(this);
}

都执行了Dispatcherfinished()函数,来看下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/** 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()