通過該篇文章大家可以了解到如下幾點
1.首先通過一個簡單的代碼示例了解Call是什么
2.從源碼的角度分析一下Call的定義
3.分析一下Call的實現(xiàn)類,從而真正了解Call
首先我們先以一段簡短的代碼為開頭來了解一下Call在我們OkHttp中的作用.
OkHttpClient client = new OkHttpClient();
String run(String url) throws IOException {
Request request = new Request.Builder()
.url(url)
.build();
Call call = client.newCall(request);
try (Response response = call.execute()) {
return response.body().string();
}
}
從上面的代碼中我們可以簡單地看出眼溶,Call 的作用就是執(zhí)行一個準(zhǔn)備好的請求悠砚。
接下來我們從Call的定義中了解一下Call到底是什么,下面給出的是Call接口的源碼堂飞。
public interface Call {
/**
**該方法返回的是原始的請求灌旧,也就是我們上面通過client.newCall中注入的Request。
**/
Request request();
/**
**立即執(zhí)行該請求酝静,并進入阻塞狀態(tài)节榜,直到請求處理得到響應(yīng)或者發(fā)生error。
**/
Response execute() throws IOException;
/**
**異步執(zhí)行請求别智,該方法不會被阻塞,在OkHttpClient中的調(diào)度器dispatcher定義了該方法請求何時被運行稼稿,正常情況下都是立馬去執(zhí)行的薄榛,除非目前正在執(zhí)行其他的請求讳窟,在客戶端將HTTP得到的響應(yīng)(失敗異常)會調(diào)用參數(shù)Callback 將其回調(diào)出去
**/
void enqueue(Callback responseCallback);
/**
**取消請求,如果請求已經(jīng)執(zhí)行結(jié)束了敞恋,則無法取消
**/
void cancel();
/**
**
請求是否已經(jīng)執(zhí)行丽啡,如果調(diào)用了execute()或者enqueue()方法,則返回true
**/
boolean isExecuted();
/**
**請求是否已取消
**/
boolean isCanceled();
interface Factory {
Call newCall(Request request);
}
}
從上面的代碼中硬猫,我們可以了解到Call大致有以下幾個功能:
- 獲取原始請求
- 同步阻塞的方式執(zhí)行請求
- 異步分阻塞的方式執(zhí)行請求
- 在請求結(jié)束前可以取消請求
- 查看當(dāng)前請求是否被執(zhí)行
- 查看當(dāng)前請求是否被取消
其實Call只有一個實現(xiàn)類RealCall补箍,我們最上面的代碼中通過call.newCall構(gòu)造的Call就是我們的RealCall。
@Override public Call newCall(Request request) {
return new RealCall(this, request);
}
接下來我們通過它的部分源碼了解一下RealCall啸蜜。
final class RealCall implements Call {
private final OkHttpClient client;
private boolean executed;
volatile boolean canceled;
Request originalRequest;
/**
**Http執(zhí)行引擎坑雅,也就是真正執(zhí)行Http請求的類。
**/
HttpEngine engine;
@Override public Response execute() throws IOException {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
try {
client.dispatcher().executed(this);
Response result = getResponseWithInterceptorChain(false);
if (result == null) throw new IOException("Canceled");
return result;
} finally {
client.dispatcher().finished(this);
}
}
@Override public void enqueue(Callback responseCallback) {
enqueue(responseCallback, false);
}
void enqueue(Callback responseCallback, boolean forWebSocket) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
client.dispatcher().enqueue(new AsyncCall(responseCallback, forWebSocket));
}
@Override public void cancel() {
canceled = true;
if (engine != null) engine.cancel();
}
@Override public synchronized boolean isExecuted() {
return executed;
}
@Override public boolean isCanceled() {
return canceled;
}
首先看一下我們的execute方法衬横,內(nèi)部通過synchronized保證每個RealCall只能執(zhí)行一次execute裹粤,而且內(nèi)部通過dispatcher執(zhí)行我們的請求,那接下來我們看一下Dispatcher的源碼蜂林。
public final class Dispatcher {
private int maxRequests = 64;
private int maxRequestsPerHost = 5;
/** Executes calls. Created lazily. */
private 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<>();
public Dispatcher(ExecutorService executorService) {
this.executorService = executorService;
}
從上面的源碼可以看出遥诉,內(nèi)部封裝了一個線程池和三個隊列,分別是準(zhǔn)備好的異步Call隊列和正在運行的異步Call隊列和正在運行的同步Call隊列噪叙。
那我們看看Dispatcher中對應(yīng)于RealCall中的executed方法矮锈。
synchronized void executed(RealCall call) {
runningSyncCalls.add(call);
}
內(nèi)部就是將對應(yīng)的Call加入同步隊列。
1: Response result = getResponseWithInterceptorChain(false);
2: private Response getResponseWithInterceptorChain(boolean forWebSocket) throws IOException {
Interceptor.Chain chain = new ApplicationInterceptorChain(0, originalRequest, forWebSocket);
return chain.proceed(originalRequest);
}
3: 通過執(zhí)行引擎HttpEngine執(zhí)行請求睁蕾。
engine = new HttpEngine(client, request, false, false, forWebSocket, null, null, null);
接下來我們看一下Dispatcher中對應(yīng)于RealCall中的enqueue方法愕难。
void enqueue(Callback responseCallback, boolean forWebSocket) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
client.dispatcher().enqueue(new AsyncCall(responseCallback, forWebSocket));
}
該方法通過構(gòu)造一份異步的Call,然后在Dispatcher中的線程池執(zhí)行惫霸。
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
好了猫缭,到目前為止,大家已經(jīng)了解了Call在OkHttp中所起到的作用壹店。