基本使用
-
異步GET
Request.Builder builder = new Request.Builder().url("https://www.baidu.com/"); builder.method("GET",null); Request build = builder.build(); OkHttpClient client = new OkHttpClient(); Call call = client.newCall(build); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { System.out.println(response.body().string()); } });
-
異步POST
FormBody.Builder builder = new FormBody.Builder().add("XXX", "XXX"); FormBody build = builder.build(); Request request = new Request.Builder().url("https://.........").post(build).build(); OkHttpClient client = new OkHttpClient(); Call call = client.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { System.out.println(response.body().string()); } });
用法都非常簡單巍佑,只用簡單的調(diào)用一下,就能實(shí)現(xiàn)所想需要實(shí)現(xiàn)的GET苛预,POST請求句狼。
源碼分析
我們還是從請求處理開始分析起:
Call call = client.newCall(request);
我們通常就會(huì)這樣聲明一個(gè) Call 對象 然后執(zhí)行異步 enqueue() 或者同步 execute()方法。
點(diǎn)進(jìn) newCall 里面:
@Override public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}
這里實(shí)際就是返回了 RealCall 這個(gè)對象热某, 而接下來 網(wǎng)絡(luò)請求 實(shí)際上就是調(diào)用 RealCall 的里面的方法腻菇。
分析 -- 異步enqueue()
@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));
}
從上面可以得知請求是從 dispatcher 完成的。
接下來分析 dispatcher
在 Dispatcher.java 下
先看看這個(gè)類所定義的變量吧
最大并發(fā)請求數(shù)
private int maxRequests = 64;
每個(gè)主機(jī)最大的請求數(shù)
private int maxRequestsPerHost = 5;
/** Executes calls. Created lazily. */
消費(fèi)者線程池
private @Nullable ExecutorService executorService;
/** Ready async calls in the order they'll be run. */
將要運(yùn)行的異步請求隊(duì)列
private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();
/** Running asynchronous calls. Includes canceled calls that haven't finished yet. */
正在運(yùn)行的異步請求隊(duì)列
private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();
/** Running synchronous calls. Includes canceled calls that haven't finished yet. */
正在運(yùn)行的同步請求隊(duì)列
private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();
由此可以看出他維護(hù)個(gè)各種隊(duì)列昔馋,把不同的Call放置相對應(yīng)的隊(duì)列中去筹吐,隊(duì)列中的請求最后會(huì)一個(gè)個(gè)的進(jìn)行訪問。
接下來看看構(gòu)造函數(shù)
/** Executes calls. Created lazily. */
private @Nullable ExecutorService executorService;
public Dispatcher(ExecutorService executorService) {
this.executorService = executorService;
}
public Dispatcher() {
}
構(gòu)造函數(shù)有兩個(gè)秘遏,一個(gè)構(gòu)造函數(shù)是帶參的丘薛,這個(gè)參數(shù)就是自己實(shí)現(xiàn)的線程池,如果我們調(diào)用不帶參的構(gòu)造函數(shù)時(shí)邦危,executorService沒有被初始化洋侨。而為他初始化的方法是 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;
}
從上面看到他會(huì)創(chuàng)建一個(gè)默認(rèn)的線程池 舍扰。
那么接下來在異步請求的時(shí)候會(huì)調(diào)用enqueue() 方法 ,而從下面我們可以看到 當(dāng)異步請求隊(duì)列 數(shù)量小于 64 并且正在運(yùn)行的請求主機(jī)數(shù)小于5時(shí)希坚,會(huì)把請求放置在 runningAsyncCalls 中 并在線程池中執(zhí)行边苹。 否則就加入到 readyAsyncCalls 中進(jìn)行緩存。
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
然后就會(huì)執(zhí)行以下方法
executorService().execute(call);
executorService()會(huì)返回一個(gè)線程池 裁僧, 如果使用的是默認(rèn)線程池的話:那么在 ThreadPoolExecutor 內(nèi) 个束,所要傳進(jìn)去的是 Runnable 這個(gè)接口,
public void execute(Runnable command) {
.....
}
再看看 AsyncCall 這個(gè)類吧 :
AsyncCall 是 RealCall 的 內(nèi)部類 聊疲。 他繼承了NamedRunnable茬底,而NamedRunnable正是實(shí)現(xiàn)了Runnable方法。
在NamedRunnable里面實(shí)現(xiàn)了run() 方法 获洲,run() 里面調(diào)用了他的一個(gè) 抽象方法 :
protected abstract void execute();
那么子類就只要實(shí)現(xiàn) execute 方法就可以了:
所以就回到了 AsyncCall 中實(shí)現(xiàn)的 execute() 方法
@Override protected void execute() {
try{
......
} finally {
client.dispatcher().finished(this);
}
}
先來看看這個(gè)方法最后都做了什么吧 :
無論如何都會(huì)調(diào)用到 client.dispatcher().finished(this); 這個(gè)方法
進(jìn)去 finished 方法 阱表,我們看到最后調(diào)用的方法為以下:
void finished(AsyncCall call) {
finished(runningAsyncCalls, call, true);
}
private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
int runningCallsCount;
Runnable idleCallback;
synchronized (this) {
注 1
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();
}
}
從上面可以看到 calls 是 runningAsyncCalls ,首先他先從隊(duì)列移除昌妹,然后執(zhí)行
promoteCalls() 捶枢,隨后將更新 runningCallsCount 和 idleCallback 。
主要的方法就是 promoteCalls()
private void promoteCalls() {
if (runningAsyncCalls.size() >= maxRequests) return; // Already running max capacity.
if (readyAsyncCalls.isEmpty()) return; // No ready calls to promote.
for (Iterator<AsyncCall> 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.
}
}
從for語句可以明顯看出 因?yàn)?runningAsyncCalls 的請求被移除了 飞崖, 那么就會(huì)從 readyAsyncCalls 中拿出請求向 runningAsyncCalls 補(bǔ)充 烂叔。
接著我們回到 execute() 方法 ,看看其中實(shí)現(xiàn)了什么:
@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);
}
}
從名字可以看出 Response 就是請求的結(jié)果固歪, 而網(wǎng)絡(luò)請求交給了
getResponseWithInterceptorChain()
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);
}
構(gòu)建了一大堆攔截器蒜鸡,最后 創(chuàng)建了 RealInterceptorChain 這個(gè) 對象,他實(shí)際作用就是一個(gè) 攔截鏈 牢裳。
最后把請求交給了攔截鏈的proceed () 方法:
@Override public Response proceed(Request request) throws IOException {
return proceed(request, streamAllocation, httpCodec, connection);
}
public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
RealConnection connection) throws IOException {
.....
注 1
RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
writeTimeout);
Interceptor interceptor = interceptors.get(index);
Response response = interceptor.intercept(next);
.....
return response;
}
注 1 : 從上面可以看出了這個(gè)攔截鏈會(huì)不斷的調(diào)用下一個(gè)攔截器逢防。從而現(xiàn)在分析一下所添加的攔截器吧。
在getResponseWithInterceptorChain() 方法中蒲讯,里面就是添加了一堆攔截器
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));
在拿取攔截鏈里面的攔截器忘朝,然后一一執(zhí)行。
retryAndFollowUpInterceptor -- 這攔截器主要是做重試判帮,網(wǎng)絡(luò)錯(cuò)誤局嘁,以及請求重定向的一些操作。
BridgeInterceptor -- 這個(gè)攔截器晦墙,主要把用戶的請求轉(zhuǎn)換為網(wǎng)絡(luò)的請求悦昵,負(fù)責(zé)對Request和Response報(bào)文進(jìn)行加工。
CacheInterceptor -- 緩存攔截器
ConnectInterceptor -- 連接攔截器晌畅,主要是處理連接服務(wù)器但指,以及http , https的包裝
CallServerInterceptor -- 服務(wù)攔截器,主要是發(fā)送(write棋凳、input)、讀忍巴瘛(read卢肃、output)數(shù)據(jù)才顿。也是攔截器的最后一個(gè)環(huán)節(jié)莫湘,這里就真正拿到了網(wǎng)絡(luò)的結(jié)果了。
攔截器會(huì)不斷的調(diào)用下一個(gè)攔截器郑气,最后全部執(zhí)行完幅垮。在每個(gè)攔截器里面,你可以看到類似的代碼 : Response networkResponse = chain.proceed(...); 這就是調(diào)用了下一個(gè)攔截器尾组。
攔截器所要執(zhí)行的內(nèi)容基本就如上的簡述了忙芒。