OKhttp原始碼解析---OkHttpClient建立
阿新 • • 發佈:2019-02-02
OkHttpC客戶端是通過new OkHttpClient()建立的,我們看下里面都做了什麼
首先是一些static的初始化
這裡主要是一些http協議和連線配置,然後是初始化了一個Internal.instance的變數,這個變數我們後面會用到。private static final List<Protocol> DEFAULT_PROTOCOLS = Util.immutableList( Protocol.HTTP_2, Protocol.SPDY_3, Protocol.HTTP_1_1); private static final List<ConnectionSpec> DEFAULT_CONNECTION_SPECS = Util.immutableList( ConnectionSpec.MODERN_TLS, ConnectionSpec.COMPATIBLE_TLS, ConnectionSpec.CLEARTEXT); static { Internal.instance = new Internal() { @Override public void addLenient(Headers.Builder builder, String line) { builder.addLenient(line); } @Override public void addLenient(Headers.Builder builder, String name, String value) { builder.addLenient(name, value); } @Override public void setCache(OkHttpClient.Builder builder, InternalCache internalCache) { builder.setInternalCache(internalCache); } @Override public boolean connectionBecameIdle( ConnectionPool pool, RealConnection connection) { return pool.connectionBecameIdle(connection); } @Override public RealConnection get( ConnectionPool pool, Address address, StreamAllocation streamAllocation) { return pool.get(address, streamAllocation); } @Override public void put(ConnectionPool pool, RealConnection connection) { pool.put(connection); } @Override public RouteDatabase routeDatabase(ConnectionPool connectionPool) { return connectionPool.routeDatabase; } @Override public StreamAllocation callEngineGetStreamAllocation(Call call) { return ((RealCall) call).streamAllocation(); } @Override public void apply(ConnectionSpec tlsConfiguration, SSLSocket sslSocket, boolean isFallback) { tlsConfiguration.apply(sslSocket, isFallback); } @Override public HttpUrl getHttpUrlChecked(String url) throws MalformedURLException, UnknownHostException { return HttpUrl.getChecked(url); } @Override public void setCallWebSocket(Call call) { ((RealCall) call).setForWebSocket(); } }; }
接下來看下OkHttpClient的建構函式
public OkHttpClient() {
this(new Builder());
}
Builder是它的內部類
這裡主要是一些變數的初始化。public Builder() { dispatcher = new Dispatcher(); protocols = DEFAULT_PROTOCOLS; connectionSpecs = DEFAULT_CONNECTION_SPECS; proxySelector = ProxySelector.getDefault(); cookieJar = CookieJar.NO_COOKIES; socketFactory = SocketFactory.getDefault(); hostnameVerifier = OkHostnameVerifier.INSTANCE; certificatePinner = CertificatePinner.DEFAULT; proxyAuthenticator = Authenticator.NONE; authenticator = Authenticator.NONE; connectionPool = new ConnectionPool(); dns = Dns.SYSTEM; followSslRedirects = true; followRedirects = true; retryOnConnectionFailure = true; connectTimeout = 10_000; readTimeout = 10_000; writeTimeout = 10_000; }
Dispatcher是用來排程非同步請求執行的,我們可以看下它的一些成員變數
maxRequestsPerHost說明當前連線請求地址的連線的最大數量,而maxRequests是總的最大連線數private int maxRequests = 64; private int maxRequestsPerHost = 5; private Runnable idleCallback; /** 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<>();
ProxySelector是連線代理伺服器,它可以它根據不同的連線使用不同的代理伺服器。系統預設的ProxySelector會檢測各種系統屬性和URL協議,然後決定怎樣連線不同的主機。
SocketFactory用來建立socket,這裡也使用的預設的
OkHostnameVerifier、Authenticator和CertificatePinner是認證相關的
然後最重要的是建立了一個ConnectionPool連線池
public ConnectionPool() {
this(5, 5, TimeUnit.MINUTES);
}
<pre name="code" class="java"> public ConnectionPool(int maxIdleConnections, long keepAliveDuration, TimeUnit timeUnit) {
this.maxIdleConnections = maxIdleConnections;
this.keepAliveDurationNs = timeUnit.toNanos(keepAliveDuration);
// Put a floor on the keep alive duration, otherwise cleanup will spin loop.
if (keepAliveDuration <= 0) {
throw new IllegalArgumentException("keepAliveDuration <= 0: " + keepAliveDuration);
}
}
設定最大空閒連線數,保持連線的時間
回到前面的初始化函式,最後是設定Dns,以及連線超時,讀超時,寫超時時間
Builder建立完成之後會用他初始化OkHttpClient
private 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.proxySelector = builder.proxySelector;
this.cookieJar = builder.cookieJar;
this.cache = builder.cache;
this.internalCache = builder.internalCache;
this.socketFactory = builder.socketFactory;
boolean isTLS = false;
for (ConnectionSpec spec : connectionSpecs) {
isTLS = isTLS || spec.isTls();
}
if (builder.sslSocketFactory != null || !isTLS) {
this.sslSocketFactory = builder.sslSocketFactory;
this.certificateChainCleaner = builder.certificateChainCleaner;
} else {
X509TrustManager trustManager = systemDefaultTrustManager();
this.sslSocketFactory = systemDefaultSslSocketFactory(trustManager);
this.certificateChainCleaner = CertificateChainCleaner.get(trustManager);
}
this.hostnameVerifier = builder.hostnameVerifier;
this.certificatePinner = builder.certificatePinner.withCertificateChainCleaner(
certificateChainCleaner);
this.proxyAuthenticator = builder.proxyAuthenticator;
this.authenticator = builder.authenticator;
this.connectionPool = builder.connectionPool;
this.dns = builder.dns;
this.followSslRedirects = builder.followSslRedirects;
this.followRedirects = builder.followRedirects;
this.retryOnConnectionFailure = builder.retryOnConnectionFailure;
this.connectTimeout = builder.connectTimeout;
this.readTimeout = builder.readTimeout;
this.writeTimeout = builder.writeTimeout;
}
這樣OkHttpClient就建立完成了。