昨天电面腾讯让说一下okhttp源码,之前看过okhttp源码but不知道怎么去下手,今天又看了一下首先从构建OkhttpClient说起吧。
mClient = new OkHttpClient.Builder()
.connectTimeout(10,TimeUnit.SECONDS)
.readTimeout(15, TimeUnit.SECONDS)
.writeTimeout(15,TimeUnit.SECONDS)
.addInterceptor(REWRITE_HEADER_CONTROL_INTERCEPTOR)
.addInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR)
.addInterceptor(new LoggingInterceptor())
// .addInterceptor(loggingInterceptor)//设置 Debug Log 模式
.cache(cache)
.cookieJar(cookieJar)
.build();
从代码中可以看出实例话client,内部用的是构建者模式接下来咱们看一下具体是怎么构建出来的。代码如下:
public static final class Builder {
Dispatcher dispatcher;
@Nullable Proxy proxy;
List protocols;
List connectionSpecs;
final List interceptors = new ArrayList<>();
final List networkInterceptors = new ArrayList<>();
EventListener.Factory eventListenerFactory;
ProxySelector proxySelector;
CookieJar cookieJar;
@Nullable Cache cache;
@Nullable InternalCache internalCache;
SocketFactory socketFactory;
@Nullable SSLSocketFactory sslSocketFactory;
@Nullable CertificateChainCleaner certificateChainCleaner;
HostnameVerifier hostnameVerifier;
CertificatePinner certificatePinner;
Authenticator proxyAuthenticator;
Authenticator authenticator;
ConnectionPool connectionPool;
Dns dns;
boolean followSslRedirects;
boolean followRedirects;
boolean retryOnConnectionFailure;
int connectTimeout;
int readTimeout;
int writeTimeout;
int pingInterval;
public Builder() {
dispatcher = new Dispatcher();
protocols = DEFAULT_PROTOCOLS;
connectionSpecs = DEFAULT_CONNECTION_SPECS;
eventListenerFactory = EventListener.factory(EventListener.NONE);
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;
pingInterval = 0;
}
Builder(OkHttpClient okHttpClient) {
this.dispatcher = okHttpClient.dispatcher;
this.proxy = okHttpClient.proxy;
this.protocols = okHttpClient.protocols;
this.connectionSpecs = okHttpClient.connectionSpecs;
this.interceptors.addAll(okHttpClient.interceptors);
this.networkInterceptors.addAll(okHttpClient.networkInterceptors);
this.eventListenerFactory = okHttpClient.eventListenerFactory;
this.proxySelector = okHttpClient.proxySelector;
this.cookieJar = okHttpClient.cookieJar;
this.internalCache = okHttpClient.internalCache;
this.cache = okHttpClient.cache;
this.socketFactory = okHttpClient.socketFactory;
this.sslSocketFactory = okHttpClient.sslSocketFactory;
this.certificateChainCleaner = okHttpClient.certificateChainCleaner;
this.hostnameVerifier = okHttpClient.hostnameVerifier;
this.certificatePinner = okHttpClient.certificatePinner;
this.proxyAuthenticator = okHttpClient.proxyAuthenticator;
this.authenticator = okHttpClient.authenticator;
this.connectionPool = okHttpClient.connectionPool;
this.dns = okHttpClient.dns;
this.followSslRedirects = okHttpClient.followSslRedirects;
this.followRedirects = okHttpClient.followRedirects;
this.retryOnConnectionFailure = okHttpClient.retryOnConnectionFailure;
this.connectTimeout = okHttpClient.connectTimeout;
this.readTimeout = okHttpClient.readTimeout;
this.writeTimeout = okHttpClient.writeTimeout;
this.pingInterval = okHttpClient.pingInterval;
}
/**
* Sets the default connect timeout for new connections. A value of 0 means no timeout,
* otherwise values must be between 1 and {@link Integer#MAX_VALUE} when converted to
* milliseconds.
*/
public Builder connectTimeout(long timeout, TimeUnit unit) {
connectTimeout = checkDuration("timeout", timeout, unit);
return this;
}
public Builder readTimeout(long timeout, TimeUnit unit) {
readTimeout = checkDuration("timeout", timeout, unit);
return this;
}
public Builder writeTimeout(long timeout, TimeUnit unit) {
writeTimeout = checkDuration("timeout", timeout, unit);
return this;
}
public Builder pingInterval(long interval, TimeUnit unit) {
pingInterval = checkDuration("interval", interval, unit);
return this;
}
private static int checkDuration(String name, long duration, TimeUnit unit) {
if (duration < 0) throw new IllegalArgumentException(name + " < 0");
if (unit == null) throw new NullPointerException("unit == null");
long millis = unit.toMillis(duration);
if (millis > Integer.MAX_VALUE) throw new IllegalArgumentException(name + " too large.");
if (millis == 0 && duration > 0) throw new IllegalArgumentException(name + " too small.");
return (int) millis;
}
public Builder proxy(@Nullable Proxy proxy) {
this.proxy = proxy;
return this;
}
public Builder proxySelector(ProxySelector proxySelector) {
this.proxySelector = proxySelector;
return this;
}
public Builder cookieJar(CookieJar cookieJar) {
if (cookieJar == null) throw new NullPointerException("cookieJar == null");
this.cookieJar = cookieJar;
return this;
}
void setInternalCache(@Nullable InternalCache internalCache) {
this.internalCache = internalCache;
this.cache = null;
}
public Builder cache(@Nullable Cache cache) {
this.cache = cache;
this.internalCache = null;
return this;
}
public Builder dns(Dns dns) {
if (dns == null) throw new NullPointerException("dns == null");
this.dns = dns;
return this;
}
public Builder socketFactory(SocketFactory socketFactory) {
if (socketFactory == null) throw new NullPointerException("socketFactory == null");
this.socketFactory = socketFactory;
return this;
}
public Builder sslSocketFactory(SSLSocketFactory sslSocketFactory) {
if (sslSocketFactory == null) throw new NullPointerException("sslSocketFactory == null");
X509TrustManager trustManager = Platform.get().trustManager(sslSocketFactory);
if (trustManager == null) {
throw new IllegalStateException("Unable to extract the trust manager on " + Platform.get()
+ ", sslSocketFactory is " + sslSocketFactory.getClass());
}
this.sslSocketFactory = sslSocketFactory;
this.certificateChainCleaner = CertificateChainCleaner.get(trustManager);
return this;
}
public Builder sslSocketFactory(
SSLSocketFactory sslSocketFactory, X509TrustManager trustManager) {
if (sslSocketFactory == null) throw new NullPointerException("sslSocketFactory == null");
if (trustManager == null) throw new NullPointerException("trustManager == null");
this.sslSocketFactory = sslSocketFactory;
this.certificateChainCleaner = CertificateChainCleaner.get(trustManager);
return this;
}
public Builder hostnameVerifier(HostnameVerifier hostnameVerifier) {
if (hostnameVerifier == null) throw new NullPointerException("hostnameVerifier == null");
this.hostnameVerifier = hostnameVerifier;
return this;
}
public Builder certificatePinner(CertificatePinner certificatePinner) {
if (certificatePinner == null) throw new NullPointerException("certificatePinner == null");
this.certificatePinner = certificatePinner;
return this;
}
public Builder authenticator(Authenticator authenticator) {
if (authenticator == null) throw new NullPointerException("authenticator == null");
this.authenticator = authenticator;
return this;
}
public Builder proxyAuthenticator(Authenticator proxyAuthenticator) {
if (proxyAuthenticator == null) throw new NullPointerException("proxyAuthenticator == null");
this.proxyAuthenticator = proxyAuthenticator;
return this;
}
public Builder connectionPool(ConnectionPool connectionPool) {
if (connectionPool == null) throw new NullPointerException("connectionPool == null");
this.connectionPool = connectionPool;
return this;
}
public Builder followSslRedirects(boolean followProtocolRedirects) {
this.followSslRedirects = followProtocolRedirects;
return this;
}
public Builder followRedirects(boolean followRedirects) {
this.followRedirects = followRedirects;
return this;
}
public Builder retryOnConnectionFailure(boolean retryOnConnectionFailure) {
this.retryOnConnectionFailure = retryOnConnectionFailure;
return this;
}
public Builder dispatcher(Dispatcher dispatcher) {
if (dispatcher == null) throw new IllegalArgumentException("dispatcher == null");
this.dispatcher = dispatcher;
return this;
}
public Builder protocols(List protocols) {
// Create a private copy of the list.
protocols = new ArrayList<>(protocols);
// Validate that the list has everything we require and nothing we forbid.
if (!protocols.contains(Protocol.HTTP_1_1)) {
throw new IllegalArgumentException("protocols doesn't contain http/1.1: " + protocols);
}
if (protocols.contains(Protocol.HTTP_1_0)) {
throw new IllegalArgumentException("protocols must not contain http/1.0: " + protocols);
}
if (protocols.contains(null)) {
throw new IllegalArgumentException("protocols must not contain null");
}
// Remove protocols that we no longer support.
protocols.remove(Protocol.SPDY_3);
// Assign as an unmodifiable list. This is effectively immutable.
this.protocols = Collections.unmodifiableList(protocols);
return this;
}
public Builder connectionSpecs(List connectionSpecs) {
this.connectionSpecs = Util.immutableList(connectionSpecs);
return this;
}
public List interceptors() {
return interceptors;
}
public Builder addInterceptor(Interceptor interceptor) {
interceptors.add(interceptor);
return this;
}
public List networkInterceptors() {
return networkInterceptors;
}
public Builder addNetworkInterceptor(Interceptor interceptor) {
networkInterceptors.add(interceptor);
return this;
}
Builder eventListener(EventListener eventListener) {
if (eventListener == null) throw new NullPointerException("eventListener == null");
this.eventListenerFactory = EventListener.factory(eventListener);
return this;
}
Builder eventListenerFactory(EventListener.Factory eventListenerFactory) {
if (eventListenerFactory == null) {
throw new NullPointerException("eventListenerFactory == null");
}
this.eventListenerFactory = eventListenerFactory;
return this;
}
public OkHttpClient build() {
return new OkHttpClient(this);
}
}
可以看出Builder是OkhttpClient的一个静态内部类,我们调用的如下的这些方法都是Builder的方法
.connectTimeout(10,TimeUnit.SECONDS)
.readTimeout(15, TimeUnit.SECONDS)
.writeTimeout(15,TimeUnit.SECONDS)
.addInterceptor(REWRITE_HEADER_CONTROL_INTERCEPTOR)
.addInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR)
.addInterceptor(new LoggingInterceptor()) //
.addInterceptor(loggingInterceptor)//设置 Debug Log 模式 .cache(cache) .cookieJar(cookieJar)
然后接下来咱们再看 .build();方法,看看这个方法的实现
public OkHttpClient build() {
return new OkHttpClient(this);
}
该方法返回了一个OkhttpClient实例并把自身传给了OkhttpClient的构造方法,接下来咱们再看一下OkhttpClient的构造方法
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;
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;
this.pingInterval = builder.pingInterval;
}
把builder里面的属性的值赋给了OkhttpClient里面的属性。
好了构建就到这了,下一篇咱们看看okhttp网络请求同步的实现