1,简介:OkHttpClient是Call的的工厂,可用于发送HTTP请求并读取其响应。 大多数应用程序可以对所有HTTP请求使用一个OkHttpClient,这得益于共享的响应缓存、线程池、连接重用等等。
2,构造方法:
public OkHttpClient() {
this(new Builder());
}
默认构造方法调用另外一个私有构造方法,需要传入一个Builder对象:
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;
} else {
try {
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, null, null);
this.sslSocketFactory = sslContext.getSocketFactory();
} catch (GeneralSecurityException e) {
//系统没有TLS。就放弃。
throw new AssertionError();
}
}
if (sslSocketFactory != null && builder.trustRootIndex == 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.trustRootIndex = Platform.get().trustRootIndex(trustManager);
this.certificatePinner = builder.certificatePinner.newBuilder()
.trustRootIndex(trustRootIndex)
.build();
} else {
this.trustRootIndex = builder.trustRootIndex;
this.certificatePinner = builder.certificatePinner;
}
this.hostnameVerifier = builder.hostnameVerifier;
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;
}
通过builder对象默认的属性对OkHttpClient里的dispatcher(调度器)、proxy(代理)、protocols(支持协议)、connectionSpecs(连接策略)、interceptors(拦截器)、networkInterceptors(网络拦截器)、proxySelector(代理选择器)、cookieJar(cookie存储)、cache(缓存)、internalCache(okHttp自己使用的缓存,不对外)、socketFactory(套接字工厂)、sslSocketFactory(ssl套接字工厂)、trustRootIndex(可信赖根)、hostnameVerifier(主机名称校验器)、certificatePinner(固定证书)、proxyAuthenticator(代理服务器授权验证)
/**
* 请求(calls)的的工厂类,可用于发送HTTP请求并读取其响应。
* 大多数应用程序可以对所有HTTP请求使用一个OkHttpClient,这得益于共享的响应缓存、线程池、连接重用等等。
* 要使用默认设置创建OkHttpClient,请使用默认构造函数。或者使用OkHttpClient.Builder创建自定义配置的实例。
* 要在发出请求之前调整现有客户端,请使用newBuilder()。
* 这个例子显示了一个超时30秒的调用:
*
* OkHttpClient client = ...
* OkHttpClient clientWith30sTimeout = client.newBuilder()
* .readTimeout(30, TimeUnit.SECONDS)
* .build();
* Response response = clientWith30sTimeout.newCall(request).execute();
*
*/
public class OkHttpClient implements Cloneable, Call.Factory {
private static final List DEFAULT_PROTOCOLS = Util.immutableList(
Protocol.HTTP_2, Protocol.SPDY_3, Protocol.HTTP_1_1);
private static final List 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(Builder builder, InternalCache internalCache) {
builder.setInternalCache(internalCache);
}
@Override
public InternalCache internalCache(OkHttpClient client) {
return client.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 void callEnqueue(Call call, Callback responseCallback, boolean forWebSocket) {
((RealCall) call).enqueue(responseCallback, forWebSocket);
}
@Override
public StreamAllocation callEngineGetStreamAllocation(Call call) {
return ((RealCall) call).engine.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);
}
};
}
final Dispatcher dispatcher;
final Proxy proxy;
final List protocols;
final List connectionSpecs;
final List interceptors;
final List networkInterceptors;
final ProxySelector proxySelector;
final CookieJar cookieJar;
final Cache cache;
final InternalCache internalCache;
final SocketFactory socketFactory;
final SSLSocketFactory sslSocketFactory;
final TrustRootIndex trustRootIndex;
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;
public OkHttpClient() {
this(new Builder());
}
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;
} else {
try {
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, null, null);
this.sslSocketFactory = sslContext.getSocketFactory();
} catch (GeneralSecurityException e) {
//系统没有TLS。就放弃。
throw new AssertionError();
}
}
if (sslSocketFactory != null && builder.trustRootIndex == 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.trustRootIndex = Platform.get().trustRootIndex(trustManager);
this.certificatePinner = builder.certificatePinner.newBuilder()
.trustRootIndex(trustRootIndex)
.build();
} else {
this.trustRootIndex = builder.trustRootIndex;
this.certificatePinner = builder.certificatePinner;
}
this.hostnameVerifier = builder.hostnameVerifier;
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;
}
/**
* 默认的连接超时(以毫秒为单位)
*/
public int connectTimeoutMillis() {
return connectTimeout;
}
/**
* 默认的读超时(以毫秒为单位)
*/
public int readTimeoutMillis() {
return readTimeout;
}
/**
* 默认的写超时(以毫秒为单位)
*/
public int writeTimeoutMillis() {
return writeTimeout;
}
public Proxy proxy() {
return proxy;
}
public ProxySelector proxySelector() {
return proxySelector;
}
public CookieJar cookieJar() {
return cookieJar;
}
public Cache cache() {
return cache;
}
InternalCache internalCache() {
return cache != null ? cache.internalCache : internalCache;
}
public Dns dns() {
return dns;
}
public SocketFactory socketFactory() {
return socketFactory;
}
public SSLSocketFactory sslSocketFactory() {
return sslSocketFactory;
}
public HostnameVerifier hostnameVerifier() {
return hostnameVerifier;
}
public CertificatePinner certificatePinner() {
return certificatePinner;
}
public Authenticator authenticator() {
return authenticator;
}
public Authenticator proxyAuthenticator() {
return proxyAuthenticator;
}
public ConnectionPool connectionPool() {
return connectionPool;
}
public boolean followSslRedirects() {
return followSslRedirects;
}
public boolean followRedirects() {
return followRedirects;
}
public boolean retryOnConnectionFailure() {
return retryOnConnectionFailure;
}
public Dispatcher dispatcher() {
return dispatcher;
}
public List protocols() {
return protocols;
}
public List connectionSpecs() {
return connectionSpecs;
}
/**
* 返回一个不可变的拦截器列表,该列表观察每个请求(call)的整个持续时间:
* 从建立连接之前(如果有的话)到选择响应源之后(源服务器、缓存或者两者都选择)。
*/
public List interceptors() {
return interceptors;
}
/**
* 这些拦截器必须精确地调用Interceptor.Chain一次,因为网络拦截器短路或重复网络请求是会报错的。
*/
public List networkInterceptors() {
return networkInterceptors;
}
/**
* 准备将来某个时候要执行的request。
*/
@Override
public Call newCall(Request request) {
return new RealCall(this, request);
}
public Builder newBuilder() {
return new Builder(this);
}
public static final class Builder {
Dispatcher dispatcher;
Proxy proxy;
List protocols;
List connectionSpecs;
final List interceptors = new ArrayList<>();
final List networkInterceptors = new ArrayList<>();
ProxySelector proxySelector;
CookieJar cookieJar;
Cache cache;
InternalCache internalCache;
SocketFactory socketFactory;
SSLSocketFactory sslSocketFactory;
TrustRootIndex trustRootIndex;
HostnameVerifier hostnameVerifier;
CertificatePinner certificatePinner;
Authenticator proxyAuthenticator;
Authenticator authenticator;
ConnectionPool connectionPool;
Dns dns;
boolean followSslRedirects;
boolean followRedirects;
boolean retryOnConnectionFailure;
int connectTimeout;
int readTimeout;
int writeTimeout;
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;
}
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.proxySelector = okHttpClient.proxySelector;
this.cookieJar = okHttpClient.cookieJar;
this.internalCache = okHttpClient.internalCache;
this.cache = okHttpClient.cache;
this.socketFactory = okHttpClient.socketFactory;
this.sslSocketFactory = okHttpClient.sslSocketFactory;
this.trustRootIndex = okHttpClient.trustRootIndex;
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;
}
/**
* 为新连接设置默认连接超时。值为0表示没有超时,否则值必须在1和Integer.MAX_VALUE之间所对应转换的毫秒。
*/
public Builder connectTimeout(long timeout, TimeUnit unit) {
if (timeout < 0) throw new IllegalArgumentException("timeout < 0");
if (unit == null) throw new IllegalArgumentException("unit == null");
long millis = unit.toMillis(timeout);
if (millis > Integer.MAX_VALUE) throw new IllegalArgumentException("Timeout too large.");
if (millis == 0 && timeout > 0) throw new IllegalArgumentException("Timeout too small.");
connectTimeout = (int) millis;
return this;
}
/**
* 为新连接设置默认读超时。值为0表示没有超时,否则值必须在1和Integer.MAX_VALUE之间所对应转换的毫秒。
*/
public Builder readTimeout(long timeout, TimeUnit unit) {
if (timeout < 0) throw new IllegalArgumentException("timeout < 0");
if (unit == null) throw new IllegalArgumentException("unit == null");
long millis = unit.toMillis(timeout);
if (millis > Integer.MAX_VALUE) throw new IllegalArgumentException("Timeout too large.");
if (millis == 0 && timeout > 0) throw new IllegalArgumentException("Timeout too small.");
readTimeout = (int) millis;
return this;
}
/**
* 为新连接设置默认写超时。值为0表示没有超时,否则值必须在1和Integer.MAX_VALUE之间所对应转换的毫秒。
*/
public Builder writeTimeout(long timeout, TimeUnit unit) {
if (timeout < 0) throw new IllegalArgumentException("timeout < 0");
if (unit == null) throw new IllegalArgumentException("unit == null");
long millis = unit.toMillis(timeout);
if (millis > Integer.MAX_VALUE) throw new IllegalArgumentException("Timeout too large.");
if (millis == 0 && timeout > 0) throw new IllegalArgumentException("Timeout too small.");
writeTimeout = (int) millis;
return this;
}
/**
* 设置此client创建的连接将使用的HTTP代理。
* 这优先于proxySelector,proxySelector只在这个代理为null(默认为null)时才被使用。
* 要完全禁用代理使用,请调用setProxy(Proxy.no_proxy)。
*/
public Builder proxy(Proxy proxy) {
this.proxy = proxy;
return this;
}
/**
* 如果没有显式指定代理{@link #proxy 代理} ,则这时设置的代理选择策略将被使用。
* 代理选择器可以返回多个代理;在这种情况下,他们将依次进行尝试,直到建立成功的连接。
* 如果未设置,将使用系统范围内的{@link ProxySelector#getDefault() 默认代理选择器}。
*/
public Builder proxySelector(ProxySelector proxySelector) {
this.proxySelector = proxySelector;
return this;
}
/**
* 设置可以接受来自传入HTTP响应的cookie的处理程序,并向发出的HTTP请求提供cookie。
* 如果未设置,则不接受或不提供cookie{@linkplain CookieJar#NO_COOKIES (no cookies)}
*/
public Builder cookieJar(CookieJar cookieJar) {
if (cookieJar == null) {
throw new NullPointerException("cookieJar == null");
}
this.cookieJar = cookieJar;
return this;
}
/**
* 设置response缓存,用于读写缓存的response。
*/
void setInternalCache(InternalCache internalCache) {
this.internalCache = internalCache;
this.cache = null;
}
public Builder cache(Cache cache) {
this.cache = cache;
this.internalCache = null;
return this;
}
/**
* 设置用于查找主机名的IP地址的DNS服务。
* 如果未设置,将使用{@link Dns#SYSTEM 系统范围内的默认DNS}。
*/
public Builder dns(Dns dns) {
if (dns == null) {
throw new NullPointerException("dns == null");
}
this.dns = dns;
return this;
}
/**
* 设置用于创建连接的套接字工厂。
* OkHttp仅使用无参数的{@link SocketFactory#createSocket() createSocket()}方法创建未连接的套接字。重写这个方法,例如。,允许套接字绑定到特定的本地地址。
* 如果未设置,将使用{@link SocketFactory#getDefault() 系统范围内的默认套接字工厂}。
*/
public Builder socketFactory(SocketFactory socketFactory) {
if (socketFactory == null) {
throw new NullPointerException("socketFactory == null");
}
this.socketFactory = socketFactory;
return this;
}
/**
* 设置用于保护HTTPS连接的套接字工厂。
* 如果未设置,将使用惰性创建的SSL套接字工厂。
*/
public Builder sslSocketFactory(SSLSocketFactory sslSocketFactory) {
if (sslSocketFactory == null) {
throw new NullPointerException("sslSocketFactory == null");
}
this.sslSocketFactory = sslSocketFactory;
this.trustRootIndex = null;
return this;
}
/**
* 设置用于确认response证书应用于HTTPS连接所请求的主机名的验证程序。
* 如果未设置,将使用默认主机名验证器
*/
public Builder hostnameVerifier(HostnameVerifier hostnameVerifier) {
if (hostnameVerifier == null) {
throw new NullPointerException("hostnameVerifier == null");
}
this.hostnameVerifier = hostnameVerifier;
return this;
}
/**
* 设置约束哪些证书受信任的固定证书。
* 默认情况下,HTTPS连接仅依赖SSL套接字工厂来建立信任。
* 固定证书可以避免信任证书颁发机构。
*/
public Builder certificatePinner(CertificatePinner certificatePinner) {
if (certificatePinner == null) {
throw new NullPointerException("certificatePinner == null");
}
this.certificatePinner = certificatePinner;
return this;
}
/**
* 设置用于响应来自源服务器的挑战的验证器。使用{@link #proxyAuthenticator} 设置代理服务器的authenticator。
* 如果未设置,将尝试 {@linkplain Authenticator#NONE 无身份验证}。
*/
public Builder authenticator(Authenticator authenticator) {
if (authenticator == null) {
throw new NullPointerException("authenticator == null");
}
this.authenticator = authenticator;
return this;
}
/**
* 设置用于响应来自代理服务器的挑战的验证器。使用{@link #authenticator}设置原始服务器的authenticator。
* 如果未设置,将尝试{@linkplain Authenticator#NONE 无身份验证}。
*/
public Builder proxyAuthenticator(Authenticator proxyAuthenticator) {
if (proxyAuthenticator == null) {
throw new NullPointerException("proxyAuthenticator == null");
}
this.proxyAuthenticator = proxyAuthenticator;
return this;
}
/**
* 设置连接池,用于循环使用HTTP和HTTPS连接。
* 如果没有设置,将会使用一个新的连接池。
*/
public Builder connectionPool(ConnectionPool connectionPool) {
if (connectionPool == null) {
throw new NullPointerException("connectionPool == null");
}
this.connectionPool = connectionPool;
return this;
}
/**
* 配置此client以遵循从HTTPS到HTTP以及从HTTP到HTTPS的重定向。
* 如果未设置,则遵循协议重定向。这与内置{@code HttpURLConnection}的默认值不同。
*/
public Builder followSslRedirects(boolean followProtocolRedirects) {
this.followSslRedirects = followProtocolRedirects;
return this;
}
/**
* 配置此client以遵循重定向。如果未设置,则遵循重定向。
*/
public Builder followRedirects(boolean followRedirects) {
this.followRedirects = followRedirects;
return this;
}
/**
* 配置此client在遇到连接问题时重试或不重试。默认情况下,该客户端会从以下问题中恢复过来:
*
* - 遥不可及的IP地址。如果URL的主机有多个IP地址,未能到达任何单个IP地址不会导致整个请求失败。这可以增加多宿主服务的可用性。
* - 陈旧的连接池。{@link ConnectionPool}重用套接字以减少请求延迟,但这些连接偶尔会超时。
* - 遥不可及的代理服务器。{@link ProxySelector}可用于依次尝试多个代理服务器,最终返回到直接连接。
*
* 将此设置为false以避免重试请求,这样做是具有破坏性的。在这种情况下,调用应用程序应该自行恢复连接故障。
*/
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;
}
/**
* 配置此client与远程服务器通信使用的协议。
* 默认情况下,这个client会选择最有效的传输方式,回归到更普遍的协议。
* 应用程序应该只调用此方法来避免特定的兼容性问题,比如启用SPDY时web服务器出现错误的行为。
*
* 以下是目前支持的协议:
*
*
*
* This is an evolving set. Future releases include support for transitional
* protocols. The http/1.1 transport will never be dropped.
*
*
If multiple protocols are specified, ALPN will be used to
* negotiate a transport.
*
*
{@link Protocol#HTTP_1_0} is not supported in this set. Requests are initiated with {@code
* HTTP/1.1} only. If the server responds with {@code HTTP/1.0}, that will be exposed by {@link
* Response#protocol()}.
*
* @param protocols the protocols to use, in order of preference. The list must contain {@link
* Protocol#HTTP_1_1}. It must not contain null or {@link Protocol#HTTP_1_0}.
*/
public Builder protocols(List protocols) {
protocols = Util.immutableList(protocols);
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");
}
this.protocols = Util.immutableList(protocols);
return this;
}
public Builder connectionSpecs(List connectionSpecs) {
this.connectionSpecs = Util.immutableList(connectionSpecs);
return this;
}
/**
* 返回一个可修改的拦截器列表,该列表可以观察每个call的整个持续时间:
* 从建立连接之前(如果有的话)到选择响应源之后(源服务器、缓存或者两者都选择)。
*/
public List interceptors() {
return interceptors;
}
public Builder addInterceptor(Interceptor interceptor) {
interceptors.add(interceptor);
return this;
}
/**
* 返回观察单个网络请求和响应的可修改的拦截器列表。
* 这些拦截器必须调用{@link Interceptor.Chain#proceed}Interceptor.Chain一次:网络拦截器短路或重复网络请求会报错。
*/
public List networkInterceptors() {
return networkInterceptors;
}
public Builder addNetworkInterceptor(Interceptor interceptor) {
networkInterceptors.add(interceptor);
return this;
}
public OkHttpClient build() {
return new OkHttpClient(this);
}
}
}