版本:com.squareup.okhttp3:okhttp:3.11.0
1、call.eventListener = client.eventListenerFactory().create(call)
建立連接(tcp锄禽、tls)
2吓妆、client.dispatcher().enqueue(new AsyncCall(responseCallback));
dispatcher(): 處理線程
enqueue(..): 成立的情況下就會去讓線程管理去管理線程,讓 call 在后臺去執(zhí)行瓮钥,
如果不成立則會添加到 readyAsyncCalls 隊(duì)列中,一個(gè)待用的隊(duì)列,隨時(shí)可能發(fā)送請求
AsyncCall:會調(diào)用父類run方法中的 execute()汉匙,實(shí)現(xiàn)在 RealCall 的 execute() 中。
@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);
}
}
}
3生蚁、okhttpclient配置項(xiàng)
final Dispatcher dispatcher;線程調(diào)度管理器
final @Nullable Proxy proxy;設(shè)置代理服務(wù)器噩翠,如果我們無法訪問或訪問失敗我們的目標(biāo)服務(wù)器,可以交給代理服務(wù)器去幫我們訪問想要訪問的目標(biāo)服務(wù)器
final List<Protocol> protocols; 所支持的 http 協(xié)議版本
final List<ConnectionSpec> connectionSpecs;配置使用http還是https;包括SSL和TLS版本的選擇配置
final List<Interceptor> interceptors;
final List<Interceptor> networkInterceptors;
final EventListener.Factory eventListenerFactory;
final ProxySelector proxySelector;
final CookieJar cookieJar;cookie存儲器
final @Nullable Cache cache;http的cache
final @Nullable InternalCache internalCache;
final SocketFactory socketFactory;創(chuàng)建tcp端口
final @Nullable SSLSocketFactory sslSocketFactory;創(chuàng)建SSL端口
final @Nullable CertificateChainCleaner certificateChainCleaner;整理服務(wù)器傳輸而來的證書
final HostnameVerifier hostnameVerifier;用于https中邦投,驗(yàn)證對方服務(wù)器的host
final CertificatePinner certificatePinner;做自簽名
final Authenticator proxyAuthenticator;Head中添加Authorizaion伤锚,訪問權(quán)限配置
final Authenticator authenticator;
final ConnectionPool connectionPool;連接池
final Dns dns;
final boolean followSslRedirects;當(dāng)遇到http與https互相跳轉(zhuǎn),是否跳志衣?
final boolean followRedirects;如果遇到需要跳轉(zhuǎn)的情況下屯援,是否去跳轉(zhuǎn),比如返回3xx念脯,默認(rèn)是true
final boolean retryOnConnectionFailure;請求失敗狞洋,是否重新連接
final int connectTimeout;tcp鏈接時(shí)間
final int readTimeout;下載等待響應(yīng)時(shí)間
final int writeTimeout;寫入響應(yīng)時(shí)間
final int pingInterval;針對wbsocket的,多久ping一次绿店,客戶端發(fā)送ping吉懊,服務(wù)端發(fā)送pong
//自簽名
public void mySingn() {
String hostname = "hencoder.com";
CertificatePinner certificatePinner = new CertificatePinner.Builder()
// .add(hostname, "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
.add(hostname, "sha256/rZ/xwvaoWYYzhWGtTUCUNO07mHKM82JCfdvWZm1Z7nU=")
.add(hostname, "sha256/GI75anSEdkuHj05mreE0Sd9jE6dVqUIzzXRHHlZBVbI=")
.add(hostname, "sha256/r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E=")
.build();
OkHttpClient client = new OkHttpClient.Builder()
.certificatePinner(certificatePinner)
.build();
Request request = new Request.Builder()
.url("https://" + hostname)
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.i("qqq","onFailure...");
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.i("qqq","onSuccess...");
}
});
}
4、分析execute中的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);
}
作用:將準(zhǔn)備好的請求去做網(wǎng)絡(luò)請求,然后得到響應(yīng)(response)
責(zé)任鏈模式
chain.proceed 的流程如上圖借嗽。
先做請求的前置工作怕午,然后調(diào)用proceed()方法,如果proceed()方法返回成功淹魄,則會接著去做響應(yīng)后置工作郁惜;在proceed()方法執(zhí)行過程中,又會去調(diào)用下一個(gè)攔截器的請求前置工作甲锡、proceed()兆蕉、響應(yīng)后置工作。缤沦。虎韵。
client.interceptors():做攔截工作,可以在請求前做一些處理缸废,或者在請求之后做一些處理
retryAndFollowUpInterceptor:用于網(wǎng)絡(luò)的重試工作
BridgeInterceptor:封裝request和response的過濾器包蓝,各種http參數(shù)的設(shè)置,Content-Type企量、User-Agent等等
CacheInterceptor:如果已有的cache信息测萎,還在保存期內(nèi),那么就直接使用cache中的數(shù)據(jù)届巩,則不會再去做接下來的網(wǎng)絡(luò)請求
ConnectInterceptor:在該攔截器中與TCP硅瞧、HTTPS的TLS來做交互,即建立一個(gè)TCP連接或者在TCP的連接上再疊加一個(gè)TLS連接恕汇。(該攔截器沒有后置工作)
client.networkInterceptors():配置 OkHttpClient 時(shí)設(shè)置的 networkInterceptors腕唧,一般很少用,主要用 client.interceptors()
CallServerInterceptor:負(fù)責(zé)向服務(wù)器發(fā)送請求數(shù)據(jù)瘾英、從服務(wù)器讀取響應(yīng)數(shù)據(jù)(實(shí)際網(wǎng)絡(luò)請求)
優(yōu)點(diǎn):
可以看到枣接,這里首先new了一個(gè)Interceptor的ArrayList,然后分別加入了各種各樣的Interceptor缺谴,所以當(dāng)我們默認(rèn)創(chuàng)建okHttpClient時(shí)但惶,okHttp默認(rèn)會給我們實(shí)現(xiàn)這些過濾器,每個(gè)過濾器執(zhí)行不同的任務(wù)瓣赂,這個(gè)思想太屌了有木有榆骚,每個(gè)過濾器負(fù)責(zé)自己的任務(wù)片拍,各個(gè)過濾器間相互不耦合煌集,高內(nèi)聚,低耦合捌省,對拓展放開巴拉巴拉等一系列設(shè)計(jì)思想有木有苫纤,這里可以對比一下Volley源碼中的思想,Volley的處理是將緩存,網(wǎng)絡(luò)請求等一系列操作揉在一起寫卷拘,導(dǎo)致用戶對于Volley的修改只能通過修改源碼方式喊废,而修改就必須要充分閱讀理解volley整個(gè)的流程,可能一部分的修改會影響全局的流程栗弟,而這里污筷,將不同的職責(zé)的過濾器分別單獨(dú)出來,用戶只需要對關(guān)注的某一個(gè)功能項(xiàng)進(jìn)行理解乍赫,并可以進(jìn)行擴(kuò)充修改瓣蛀,一對比,okHttp在這方面的優(yōu)勢立馬體現(xiàn)出來了雷厂。這里大概先描述一下幾個(gè)過濾器的功能
面試題
1惋增、okhttp 的原理。先重定向再查緩存改鲫?請求池诈皿?