读OkHttp3源码(一):OkHttpClient

1,简介:OkHttpClient是Call的的工厂,可用于发送HTTP请求并读取其响应。 大多数应用程序可以对所有HTTP请求使用一个OkHttpClient,这得益于共享的响应缓存线程池连接重用等等。

  • 要使用默认设置创建OkHttpClient,请使用默认构造函数。
  • 或者使用OkHttpClient.Builder创建自定义配置的实例。
  • 要在发出请求之前调整现有客户端,请使用newBuilder()。

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;
    }
/**
 * 请求(calls)的的工厂类,可用于发送HTTP请求并读取其响应。
 * 大多数应用程序可以对所有HTTP请求使用一个OkHttpClient,这得益于共享的响应缓存、线程池、连接重用等等。
 * 要使用默认设置创建OkHttpClient,请使用默认构造函数。或者使用OkHttpClient.Builder创建自定义配置的实例。
 * 要在发出请求之前调整现有客户端,请使用newBuilder()。
 * 这个例子显示了一个超时30秒的调用:
 * <pre>
 *     OkHttpClient client = ...
 *     OkHttpClient clientWith30sTimeout = client.newBuilder()
 *          .readTimeout(30, TimeUnit.SECONDS)
 *          .build();
 *    Response response = clientWith30sTimeout.newCall(request).execute();
 * </pre>
 */
public class OkHttpClient implements Cloneable, Call.Factory {
    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(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<Protocol> protocols;
    final List<ConnectionSpec> connectionSpecs;
    final List<Interceptor> interceptors;
    final List<Interceptor> 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<Protocol> protocols() {
        return protocols;
    }

    public List<ConnectionSpec> connectionSpecs() {
        return connectionSpecs;
    }

    /**
     * 返回一个不可变的拦截器列表,该列表观察每个请求(call)的整个持续时间:
     * 从建立连接之前(如果有的话)到选择响应源之后(源服务器、缓存或者两者都选择)。
     */
    public List<Interceptor> interceptors() {
        return interceptors;
    }

    /**
     * 这些拦截器必须精确地调用Interceptor.Chain一次,因为网络拦截器短路或重复网络请求是会报错的。
     */
    public List<Interceptor> 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<Protocol> protocols;
        List<ConnectionSpec> connectionSpecs;
        final List<Interceptor> interceptors = new ArrayList<>();
        final List<Interceptor> 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在遇到连接问题时重试或不重试。默认情况下,该客户端会从以下问题中恢复过来:
         * <ul>
         * <li><strong>遥不可及的IP地址。</strong>如果URL的主机有多个IP地址,未能到达任何单个IP地址不会导致整个请求失败。这可以增加多宿主服务的可用性。</li>
         * <li><strong>陈旧的连接池。</strong>{@link ConnectionPool}重用套接字以减少请求延迟,但这些连接偶尔会超时。</li>
         * <li><strong>遥不可及的代理服务器。</strong>{@link ProxySelector}可用于依次尝试多个代理服务器,最终返回到直接连接。</li>
         * </ul>
         * 将此设置为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服务器出现错误的行为。
         *
         * <p>以下是目前支持的协议:
         *
         * <ul>
         * <li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616.html">http/1.1</a>
         * <li><a
         * href="http://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3-1">spdy/3.1</a>
         * <li><a href="http://tools.ietf.org/html/draft-ietf-httpbis-http2-17">h2</a>
         * </ul>
         *
         * <p><strong>This is an evolving set.</strong> Future releases include support for transitional
         * protocols. The http/1.1 transport will never be dropped.
         *
         * <p>If multiple protocols are specified, <a
         * href="http://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg">ALPN</a> will be used to
         * negotiate a transport.
         *
         * <p>{@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<Protocol> 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<ConnectionSpec> connectionSpecs) {
            this.connectionSpecs = Util.immutableList(connectionSpecs);
            return this;
        }

        /**
         * 返回一个可修改的拦截器列表,该列表可以观察每个call的整个持续时间:
         * 从建立连接之前(如果有的话)到选择响应源之后(源服务器、缓存或者两者都选择)。
         */
        public List<Interceptor> interceptors() {
            return interceptors;
        }

        public Builder addInterceptor(Interceptor interceptor) {
            interceptors.add(interceptor);
            return this;
        }

        /**
         * 返回观察单个网络请求和响应的可修改的拦截器列表。
         * 这些拦截器必须调用{@link Interceptor.Chain#proceed}Interceptor.Chain一次:网络拦截器短路或重复网络请求会报错。
         */
        public List<Interceptor> networkInterceptors() {
            return networkInterceptors;
        }

        public Builder addNetworkInterceptor(Interceptor interceptor) {
            networkInterceptors.add(interceptor);
            return this;
        }

        public OkHttpClient build() {
            return new OkHttpClient(this);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/challenge51all/article/details/82897958