Okhttp源碼分析--基本使用流程分析
一、 使用
同步請求
OkHttpClient okHttpClient=new OkHttpClient();
Request request=new Request.Builder()
.get()
.url("www.baidu.com")
.build();
Call call =okHttpClient.newCall(request).execute();
異步請求
OkHttpClient okHttpClient=new OkHttpClient();
Request request=new Request.Builder()
.get()
.url("www.baidu.com")
.build();
Call call=okHttpClient.newCall(request).enqueue(new Callback() {
@Override public void onFailure(Call call, IOException e) {
Log.i(TAG, "onFailure: ");
}
@Override public void onResponse(Call call, Response response) throws IOException {
Log.i(TAG, "onResponse: ");
}
});
可以看出不管是同步還是異步請求,使用okhttp大致分爲3個步驟:
1. 創建okhttpclient
2. 創建請求的request
3. 通過client拿到call、發送請求
注:okhttpclient和request的創建均可採用構造者模式,在構造過程中可根據自己的實際需求設置相應的參數,如可在okhttpclient構造時添加自定義攔截器,在request構造過程中設置連接超時時間等。
二、 源碼分析
首先看下OkhttpClient這個類,使用步驟的第一步就是構造OkhttpClient對象。
先貼下官方對OkhttpClient的定義
*Factory for {@linkplain Call calls}, which can be used to send HTTP requests and read their
* responses.
* OkHttpClients should be shared
* OkHttp performs best when you create a single {@code OkHttpClient} instance and reuse it for
* all of your HTTP calls. This is because each client holds its own connection pool and thread
* pools. Reusing connections and threads reduces latency and saves memory. Conversely, creating a
* client for each request wastes resources on idle pools.
OkhttpClient是用於發送請求和讀取響應的,官方建議創建一個單例的OkHttpClient,並且所有的http請求都複用它。因爲每個OkHttpClient都有自己的connection pool and thread pool。複用connection pool and thread pool可以節約內存,相反如果爲每個請求都創建一個OkHttpClient那麼會浪費idle pools中的資源。
創建OkHttpClient有兩種方式:
1、通過構造函數
2、通過Builder()創建一個client並自定義設置
同時還提供了一個newBuilder()來自定義client,它跟共享的client擁有相同的connection pool, thread pools, and configuration。我們可以用該方法來獲取特定設置的client。
OkHttpClient提供無參構造函數,由代碼可知它在內部調用OkHttpClient的有參構造函數
,在有參構造函數裏對OkHttpClient主要屬性做了初始化賦值。
public OkHttpClient() {
this(new Builder());
}
OkHttpClient(Builder builder) {
this.dispatcher = builder.dispatcher;
this.proxy = builder.proxy;
this.protocols = builder.protocols;
this.connectionSpecs = builder.connectionSpecs;
this.interceptors = Util.immutableList(builder.interceptors);
this.networkInterceptors = Util.immutableList(builder.networkInterceptors);
this.eventListenerFactory = builder.eventListenerFactory;
this.proxySelector = builder.proxySelector;
this.cookieJar = builder.cookieJar;
this.cache = builder.cache;
this.internalCache = builder.internalCache;
this.socketFactory = builder.socketFactory;
...//省略N行
}
下面貼下OkHttpClient主要的屬性
public class OkHttpClient{
final Dispatcher dispatcher;//分發器
final @Nullable Proxy proxy;//代理
final List<Protocol> protocols;//協議
final List<ConnectionSpec> connectionSpecs;//傳輸層版本和連接協議
final List<Interceptor> interceptors;//攔截器 (okhttp核心機制)
final List<Interceptor> networkInterceptors;//網絡攔截器
final EventListener.Factory eventListenerFactory;
final ProxySelector proxySelector;//代理選擇器
final CookieJar cookieJar;//cookie
final @Nullable
Cache cache;//cache 緩存
final @Nullable
InternalCache internalCache;//內部緩存
final SocketFactory socketFactory;//socket 工廠
final @Nullable
SSLSocketFactory sslSocketFactory;//安全套層socket工廠 用於https
final @Nullable
CertificateChainCleaner certificateChainCleaner;//驗證確認響應書,適用HTTPS 請求連接的主機名
final HostnameVerifier hostnameVerifier;//主機名字確認
final CertificatePinner certificatePinner;//證書鏈
final Authenticator proxyAuthenticator;//代理身份驗證
final Authenticator authenticator;//本地省份驗證
final ConnectionPool connectionPool;//鏈接池 複用連接
final Dns dns; //域名
final boolean followSslRedirects;//安全套接層重定向
final boolean followRedirects;//本地重定向
final boolean retryOnConnectionFailure;//連接失敗是否重試
final int connectTimeout;//連接超時時間
final int readTimeout;//讀取超時時間
final int writeTimeout;//寫入超時時間
}
通過瀏覽源碼我們可以發現OkHttpClient採用了構造者設計模式,這樣簡化參數設置,降低使用成本。比如我們前面簡單使用的例子
OkHttpClient類還有一個需要了解的函數就是newCall,因爲OkHttpClient實現Call.Factory接口所以覆寫了newCall方法,在方法內部返回的是一個RealCall實例。
/**
* Prepares the {@code request} to be executed at some point in the future.
*/
@Override public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}
OkHttpClient構造好了之後接下來就是創建request,request就是我們要發送的請求。它也是通過builder模式構造的。下面貼下Request的主要屬性以及其構造函數。
public final class Request {
final HttpUrl url;//請求url地址
final String method;//請求方式
final Headers headers;//請求頭
final @Nullable RequestBody body;//請求body
final Map<Class<?>, Object> tags;//請求tags用來標記一類請求如 設置之後可以通過tags取消擁有該tag的請求
Request(Builder builder) {
this.url = builder.url;
this.method = builder.method;
this.headers = builder.headers.build();
this.body = builder.body;
this.tags = Util.immutableMap(builder.tags);
}
...
}
通過Request我們可以得到我們想要的請求,然後下一步就是獲取call實例然後發送請求。
在介紹OkHttpClient類的時候我們已經說過call對象是通過OkHttpClient的newCall方法獲得的實際返回的是RealCall對象,也就是說真正發送的請求是RealCall,那麼我們來看下RealCall這個類
final class RealCall implements Call {
final OkHttpClient client; //realcall持有client
private Transmitter transmitter;//暫時不知道其作用
/** The application's original request unadulterated by redirects or auth headers. */
final Request originalRequest;//原始請求
final boolean forWebSocket;//
// Guarded by this.
private boolean executed;//請求是否執行標誌位
private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) { //構造函數
this.client = client;
this.originalRequest = originalRequest;
this.forWebSocket = forWebSocket;
}
static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {//okhttpclient即通過該函數返回call
// Safely publish the Call instance to the EventListener.
RealCall call = new RealCall(client, originalRequest, forWebSocket);
call.transmitter = new Transmitter(client, call);
return call;
}
RealCall實現的Call接口,其newCall函數內部通過RealCall的構造函數實例化一個call然後返回該call。
最後就是發送請求了,有兩種方式:同步和異步。我們先看下同步請求的方式,同步請求是通過execute發送的
@Override public Response execute() throws IOException {
synchronized (this) {//1
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
transmitter.timeoutEnter();
transmitter.callStart();
try {
client.dispatcher().executed(this);//2
return getResponseWithInterceptorChain();//3
} finally {
client.dispatcher().finished(this);//4
}
}
execute首先(註釋1處)會synchronized來檢查executed值從而確保每個請求只能執行一次。隨後調用dispatcher的executed(註釋2處)。
來看下Dispatcher這個類
public final class Dispatcher {
private int maxRequests = 64;//最大請求數
private int maxRequestsPerHost = 5;//每個host的最大請求數
private @Nullable Runnable idleCallback;//請求隊列空閒回調
/** Executes calls. Created lazily. */
private @Nullable 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<>();//同步請求隊列
可以看出okhttp雖然支持併發請求但是有最大併發請求數的限制。而且okhttp針對不同的請求方式提供了不同的請求隊列。dispatcher這個類主要的作用就是根據request的請求方式以及根據當前client的執行情況把新創建的call請求分發至不同的隊列中去執行。
瞭解了dispatcher類作用我們看下它的exectued函數
synchronized void executed(RealCall call) {
runningSyncCalls.add(call);
}
很簡單它只是把傳入的call對象添加到同步請求隊列中(runningSyncCalls)。那請求具體是如何發送的呢 我們接着看RealCall的exectued函數。
在註釋3處通過調用getResponseWithInterceptorChain()獲取respone並返回該respone。
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List<Interceptor> interceptors = new ArrayList<>();
interceptors.addAll(client.interceptors());//如果在client中設置了自定義interceptor那麼會放到interceptors中
interceptors.add(new RetryAndFollowUpInterceptor(client));//添加重試與重定向攔截器
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));//添加CallServer攔截器
Interceptor.Chain chain = new RealInterceptorChain(interceptors, transmitter, null, 0,
originalRequest, this, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());//
創建RealInterceptorChain實例,把interceptors傳入
boolean calledNoMoreExchanges = false;
try {
Response response = chain.proceed(originalRequest);//通過proceed鏈式獲取respone
if (transmitter.isCanceled()) {
closeQuietly(response);
throw new IOException("Canceled");
}
return response;//返回respone
} catch (IOException e) {
calledNoMoreExchanges = true;
throw transmitter.noMoreExchanges(e);
} finally {
if (!calledNoMoreExchanges) {
transmitter.noMoreExchanges(null);
}
}
}
getResponseWithInterceptorChain首先會把自定義以及okhttp定義的攔截器加到interceptors的list中,然後構造RealInterceptorChain攔截器鏈,調用chain.proceed鏈式調用各個攔截器並最終獲得respone。
Interceptor可以說是okhttp的核心機制之一,我們一起來看下
public interface Interceptor {
Response intercept(Chain chain) throws IOException;
interface Chain {
Request request();
Response proceed(Request request) throws IOException;
/**
* Returns the connection the request will be executed on. This is only available in the chains
* of network interceptors; for application interceptors this is always null.
*/
@Nullable Connection connection();
Call call();
int connectTimeoutMillis();
Chain withConnectTimeout(int timeout, TimeUnit unit);
int readTimeoutMillis();
Chain withReadTimeout(int timeout, TimeUnit unit);
int writeTimeoutMillis();
Chain withWriteTimeout(int timeout, TimeUnit unit);
}
}
它是okhttp定義的一個接口類,並且okhttp提供了5個實現類,他們就是getResponseWithInterceptorChain()中添加到interceptors中的5個Interceptor,他們作用各不相同,這個以後會單獨分析。除此之外我們還可以自定義自己的攔截器。
瞭解了攔截器的概念之後我們看下RealInterceptorChain及其proceed函數
public final class RealInterceptorChain implements Interceptor.Chain {
private final List<Interceptor> interceptors;//攔截器list
private final Transmitter transmitter;
private final @Nullable Exchange exchange;
private final int index;
private final Request request;//請求
private final Call call;
private final int connectTimeout;
private final int readTimeout;
private final int writeTimeout;
private int calls;
public RealInterceptorChain(List<Interceptor> interceptors, Transmitter transmitter,
@Nullable Exchange exchange, int index, Request request, Call call,
int connectTimeout, int readTimeout, int writeTimeout) {//構造函數
this.interceptors = interceptors;
this.transmitter = transmitter;
this.exchange = exchange;
this.index = index;
this.request = request;
this.call = call;
this.connectTimeout = connectTimeout;
this.readTimeout = readTimeout;
this.writeTimeout = writeTimeout;
}
@Override public Response proceed(Request request) throws IOException {//proceed方法實際調用同名的proceed方法
return proceed(request, transmitter, exchange);
}
public Response proceed(Request request, Transmitter transmitter, @Nullable Exchange exchange)
throws IOException {//1
if (index >= interceptors.size()) throw new AssertionError();
calls++;
// If we already have a stream, confirm that the incoming request will use it.
if (this.exchange != null && !this.exchange.connection().supportsUrl(request.url())) {
throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
+ " must retain the same host and port");
}
// If we already have a stream, confirm that this is the only call to chain.proceed().
if (this.exchange != null && calls > 1) {
throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
+ " must call proceed() exactly once");
}
// 2
//Call the next interceptor in the chain.
RealInterceptorChain next = new RealInterceptorChain(interceptors, transmitter, exchange,
index + 1, request, call, connectTimeout, readTimeout, writeTimeout);
Interceptor interceptor = interceptors.get(index);
Response response = interceptor.intercept(next);
// Confirm that the next interceptor made its required call to chain.proceed().
if (exchange != null && index + 1 < interceptors.size() && next.calls != 1) {
throw new IllegalStateException("network interceptor " + interceptor
+ " must call proceed() exactly once");
}
// Confirm that the intercepted response isn't null.
if (response == null) {
throw new NullPointerException("interceptor " + interceptor + " returned null");
}
if (response.body() == null) {
throw new IllegalStateException(
"interceptor " + interceptor + " returned a response with no body");
}
return response;
}
RealInterceptorChain作爲攔截器鏈它持有整個應用的攔截器以及網絡攔截器。該類的proceed方法實際是調用了該類重載的proceed方法(註釋1處)。在註釋2處,調用攔截器鏈中的下一個攔截器。在這裏new了一個RealInterceptorChain,注意這裏傳入的index加了1(getResponseWithInterceptorChain傳入的index爲0),這代表攔截器鏈中的下一個攔截器的index,之後根據index獲取當前的攔截器並調用其intercept方法。intercept是接口Interceptor的一個方法,由具體的實現類實現,此處我們以RetryAndFollowUpInterceptor爲例看下intercept方法中做了什麼事情。
public final class RetryAndFollowUpInterceptor implements Interceptor {
private final OkHttpClient client;//持有的client
@Override public Response intercept(Chain chain) throws IOException {
Request request = chain.request();//獲取傳入的chain的request 此處的request是next的request
RealInterceptorChain realChain = (RealInterceptorChain) chain;
Transmitter transmitter = realChain.transmitter();
int followUpCount = 0;
Response priorResponse = null;
while (true) {
transmitter.prepareToConnect(request);
if (transmitter.isCanceled()) {
throw new IOException("Canceled");
}
Response response;
boolean success = false;
try {
response = realChain.proceed(request, transmitter, null);//調用next的proceed方法
success = true;
} catch (RouteException e) {
// The attempt to connect via a route failed. The request will not have been sent.
if (!recover(e.getLastConnectException(), transmitter, false, request)) {
throw e.getFirstConnectException();
}
continue;
} catch (IOException e) {
// An attempt to communicate with a server failed. The request may have been sent.
boolean requestSendStarted = !(e instanceof ConnectionShutdownException);
if (!recover(e, transmitter, requestSendStarted, request)) throw e;
continue;
} finally {
// The network call threw an exception. Release any resources.
if (!success) {
transmitter.exchangeDoneDueToException();
}
}
// Attach the prior response if it exists. Such responses never have a body.
if (priorResponse != null) {
response = response.newBuilder()
.priorResponse(priorResponse.newBuilder()
.body(null)
.build())
.build();
}
Exchange exchange = Internal.instance.exchange(response);
Route route = exchange != null ? exchange.connection().route() : null;
Request followUp = followUpRequest(response, route);//處理請求重定向
if (followUp == null) {
if (exchange != null && exchange.isDuplex()) {
transmitter.timeoutEarlyExit();
}
return response;//直到沒有重定向之後返回respone
}
RequestBody followUpBody = followUp.body();
if (followUpBody != null && followUpBody.isOneShot()) {
return response;
}
closeQuietly(response.body());
if (transmitter.hasExchange()) {
exchange.detachWithViolence();
}
if (++followUpCount > MAX_FOLLOW_UPS) {
throw new ProtocolException("Too many follow-up requests: " + followUpCount);
}
request = followUp;
priorResponse = response;
}
}
}
我們看到在RetryAndFollowUpInterceptor的intercept方法中會調用傳入的next(即攔截器鏈中當前攔截器的下一個攔截器)的proceed方法,這樣就可以鏈式的依次調用chain中所有攔截器,每個攔截器都執行自己的任務最終返回respone。該respone通過RealCall的getResponseWithInterceptorChain返回到execute方法並最終變成我們獲得的respone。至此同步請求獲得了respone,最後的操作就是在RealCall的execute方法中調用finished方法
@Override public Response execute() throws IOException {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
transmitter.timeoutEnter();
transmitter.callStart();
try {
client.dispatcher().executed(this);
return getResponseWithInterceptorChain();
} finally {
client.dispatcher().finished(this);//拿到respone後調用finish方法
}
}
該方法是dispatcher提供的
void finished(RealCall call) {
finished(runningSyncCalls, call);
}
private <T> void finished(Deque<T> calls, T call) {
Runnable idleCallback;
synchronized (this) {
if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");//從同步執行隊列移除該call 移除失敗會拋出異常
idleCallback = this.idleCallback;
}
boolean isRunning = promoteAndExecute();//1
if (!isRunning && idleCallback != null) {
idleCallback.run();//如果isRuning爲false並且idleCallback不爲空就執行idleCallback。
}
}
我們看下promoteAndExecute()這個方法
private boolean promoteAndExecute() {
assert (!Thread.holdsLock(this));
List<AsyncCall> executableCalls = new ArrayList<>();
boolean isRunning;
synchronized (this) {
for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {//1
AsyncCall asyncCall = i.next();
if (runningAsyncCalls.size() >= maxRequests) break; // Max capacity.
if (asyncCall.callsPerHost().get() >= maxRequestsPerHost) continue; // Host max capacity.
i.remove();
asyncCall.callsPerHost().incrementAndGet();
executableCalls.add(asyncCall);
runningAsyncCalls.add(asyncCall);
}
isRunning = runningCallsCount() > 0;
}
for (int i = 0, size = executableCalls.size(); i < size; i++) {//2
AsyncCall asyncCall = executableCalls.get(i);
asyncCall.executeOn(executorService());
}
return isRunning;
}
該方法主要是兩個for循環,首先第一個for循環(註釋1處)遍歷準備就緒隊列如果不爲空且滿足一定條件則添加到executableCalls中,但是在同步請求時準備就緒隊列(readyAsyncCalls)爲空,executableCalls也爲空,所以兩個for循環都不會進入(實際上該方法是爲異步請求準備的)函數最終返回false。
此時回到dispatcher的finish()方法,它會判斷promoteAndExecute()返回值和idleCallback是否爲空,如果isRuning爲false並且idleCallback不爲空就執行idleCallback,否則就什麼都不做。
至此同步請求流程分析完畢。
異步請求
異步請求跟同步請求不同的地方就是它是調用RealCall的enqueue方法
@Override public void enqueue(Callback responseCallback) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
transmitter.callStart();
client.dispatcher().enqueue(new AsyncCall(responseCallback));//執行dispatcher的enqueue
}
在方法內部調用dispatcher的enqueue並傳入AsyncCall參數,我們先來看下AsyncCall再分析異步請求流程
final class AsyncCall extends NamedRunnable {
private final Callback responseCallback;
private volatile AtomicInteger callsPerHost = new AtomicInteger(0);
AsyncCall(Callback responseCallback) {
super("OkHttp %s", redactedUrl());
this.responseCallback = responseCallback;
}
}
AsyncCall是RealCall的一個內部類它繼承自NamedRunnable
public abstract class NamedRunnable implements Runnable {
protected final String name;
public NamedRunnable(String format, Object... args) {
this.name = Util.format(format, args);
}
@Override public final void run() {
String oldName = Thread.currentThread().getName();
Thread.currentThread().setName(name);
try {
execute();
} finally {
Thread.currentThread().setName(oldName);
}
}
protected abstract void execute();
}
NamedRunnable其實就是一個實現Runnable的線程類。在它的run方法中調用了其提供的抽象函數execute(),execute()的實現是在AsyncCall
@Override protected void execute() {
boolean signalledCallback = false;
transmitter.timeoutEnter();
try {
Response response = getResponseWithInterceptorChain();
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 {
responseCallback.onFailure(RealCall.this, e);
}
} finally {
client.dispatcher().finished(this);
}
}
可以看到這跟同步請求的過程是一樣的先通過getResponseWithInterceptorChain()鏈式調用攔截鏈去獲得resopne,之後是通過callback回調結果,最後調用finished。
分析AsyncCall之後我們可以大致猜測出異步請求的實現是通過線程去執行Call,請求的執行過程跟同步請求是一樣的只不過最後是通過callbcak返回。
好了,我們來看下具體的異步請求流程,之前說到dispatcher的enqueue方法,那我們來看下這個方法都做了什麼
void enqueue(AsyncCall call) {
synchronized (this) {
readyAsyncCalls.add(call);//添加到異步準備就緒隊列
// Mutate the AsyncCall so that it shares the AtomicInteger of an existing running call to
// the same host.
if (!call.get().forWebSocket) {
AsyncCall existingCall = findExistingCallWithHost(call.host());
if (existingCall != null) call.reuseCallsPerHostFrom(existingCall);
}
}
promoteAndExecute();//執行請求
}
很簡單在方法內部先是把call添加到異步準備就緒隊列然後調用了 promoteAndExecute,promoteAndExecute我們之前在同步請求分析過它內部主要是兩個for循環,在同步請求時這兩個for循環都是不滿足條件的,那我們看下異步請求時
private boolean promoteAndExecute() {
assert (!Thread.holdsLock(this));
List<AsyncCall> executableCalls = new ArrayList<>();
boolean isRunning;
synchronized (this) {
for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {//把異步準備就緒對列中的call取出
AsyncCall asyncCall = i.next();
//判斷最大請求數以及每個host請求數是否符合要求
if (runningAsyncCalls.size() >= maxRequests) break; // Max capacity.
if (asyncCall.callsPerHost().get() >= maxRequestsPerHost) continue; // Host max capacity.
//移除準備就緒隊列中的call
i.remove();
asyncCall.callsPerHost().incrementAndGet();//記錄該call的host的請求數
executableCalls.add(asyncCall);//添加到executableCalls
runningAsyncCalls.add(asyncCall);//添加到異步執行隊列
}
isRunning = runningCallsCount() > 0;
}
for (int i = 0, size = executableCalls.size(); i < size; i++) {//executableCalls不爲空,取出執行
AsyncCall asyncCall = executableCalls.get(i);
asyncCall.executeOn(executorService());//call實際執行
}
return isRunning;
}
因爲在之前已經把call添加到了異步準備就緒隊列(readyAsyncCalls
),所以第一個for是可以進入的,在第一個for循環內部首先會先判斷當前準備就緒隊列中的call是否達到了最大請求數即最大併發請求數,然後判斷單個host是否達到最大請求數。之後就是把當前的call添加到executableCalls和runningAsyncCalls兩個隊列中。之後進入第二個for循環,在這個for循環中依次其中取出call對象並調用其executeO函數。
注意在execute函數中傳入的executorService其實是一個線程池
public synchronized ExecutorService executorService() {
if (executorService == null) {
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue<>(), Util.threadFactory("OkHttp Dispatcher", false));
}
return executorService;
}
可以看出executorService是一個僅有非核心線程,且非核心線程數無限大的線程池。
好了簡單瞭解了executorService我們返回來接着看下executeOn,
在executeOn中調用了executorService.execute(this),executeOn是AsyncCall內部的函數而AsyncCall是一個線程類所以該操作會執行線程的run方法,這裏具體來說就是NamedRunnable的run方法,我們知道在這個run方法中調用了execute()方法,execute()我們上面分析過了跟同步請求過程一樣鏈式調用攔截器最終獲取respone。
void executeOn(ExecutorService executorService) {
assert (!Thread.holdsLock(client.dispatcher()));
boolean success = false;
try {
executorService.execute(this);//實際執行call
success = true;
} catch (RejectedExecutionException e) {
InterruptedIOException ioException = new InterruptedIOException("executor rejected");
ioException.initCause(e);
transmitter.noMoreExchanges(ioException);
responseCallback.onFailure(RealCall.this, ioException);
} finally {
if (!success) {
client.dispatcher().finished(this); // This call is no longer running!
}
}
}
至此異步請求流程也分析完了。
最後我們來總結下Okhttp的請求流程:
首先不管同步還是異步都會先初始化一個OkhttpClient之後是Request、Call。
不同之處在於同步請求把請求添加到runningSyncCalls
然後直接調用execute,鏈式調用攔截器獲取respone並返回。異步請求則是把請求先添加到readyAsyncCalls,之後執行的時候再把其添加到runningAsyncCalls並且把請求放到子線程中取執行,即鏈式調用攔截器獲取respone是在子線程中完成的。
還有就是不管是同步還是異步請求完成後都會把Call移除。
以上只是Okhttp最簡單的流程分析,其實Okhttp還有很多值得我們學習的地方,之後我會繼續更新相關內容來更深入瞭解Okhttp。