okhttp源码阅读(一)

昨天电面腾讯让说一下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网络请求同步的实现

你可能感兴趣的:(android,中级)