OkHttp源码分析(2)- OkHttpClient - OkHttp的“ApplicationContext”

系列文章目录

一、OkHttp源码分析(1)- 总体框架介绍
二、OkHttp源码分析(2)- OkHttpClient - OkHttp的“ApplicationContext”
三、OkHttp源码分析(3)- Dispatcher - 线程资源管理和分配
四、OkHttp源码分析(4)- Call - 一次完整的用户请求封装
五、OkHttp源码分析(5)- Interceptor调用链 - Http协议通信流程的实现和扩展
六、OkHttp源码分析(6)- Transmitter - OkHttp的“CallContext”
七、OkHttp源码分析(7)- Exchange层 - 连接应用层实现和传输层实现
八、OkHttp源码分析(8)- OkHttpClient的对Connection的封装和管理
九、OkHttp源码分析(9)- OkHttpClient是如果通过java.net实现网络I/O的

前言

在上一篇文章《OkHttp总体框架介绍》中,我简单的介绍了一下我对OkHttp总体架构设计的一个理解,在文章中,我对OkHttp的各个层次和各个关键的类都做了一个简单的介绍。那这一章节开始,我就开始从更加详细的角度去分析这些关键类的源码,那首当其冲的就是OkHttpClient。

OkHttpClient可以看作是OKHTTP的一个全局应用上下文,在一个应用中往往只会创建一个单例。它主要有两个功能

  • 可配置、存储和获取一些全局的属性配置,比如超时时间、自定义的CookieJar实现、自定义的Interceptor实现、添加事件监听等等。
  • 负责创建和管理一些全局单例对象,比如Dispatcher、ConnectionPool等。
  • 提供newCall API,我们用的最多也是这个API,例如:
    String respJson = okHttpClient.newCall(request).execute().body().string();
    

OKhttpClient中大部分的代码都是其属性的配置,并没有什么逻辑上的实现,所以下面我们就从其各个属性开始,去逐步了解OKhttpClient的源码。

属性

对于OkHttp的属性,我主要根据其特性和层次对其进行分类。但是这里不会出现上一篇文章架构图中描绘的所有类,因为那图中的类或者接口不是所有都对外开放的,一些是内部使用的API,例如:Transmitter、Exchange、Connection这些都不会出现在OKHttpClient中。

基础配置

这些属性主要是一些全局性的基础配置,它们中大部分都是对用户开放的,可获取可设置。它们会存储在OkHttp实例当中,并且会在全局范围内被各个层次的模块使用,主要是用来控制通信的一些基本行为,比如请求超时时间,是否SSL重定向,是否Http重定向,是否使用缓存、支持的协议等。

//协议簇-只支持HTTP_2/HTTP_1_1,并且不可修改
static final List<Protocol> DEFAULT_PROTOCOLS = Util.immutableList(Protocol.HTTP_2/, Protocol.HTTP_1_1);
//默认连接规范
//ConnectionSpec.CLEARTEXT:Http的规范配置
//ConnectionSpec.MODERN_TLS:TLS规范配置
static final List<ConnectionSpec> DEFAULT_CONNECTION_SPECS = Util.immutableList(ConnectionSpec.MODERN_TLS,ConnectionSpec.CLEARTEXT);
//是否SSL重定向
final boolean followSslRedirects;
//是否http重定向
final boolean followRedirects;
//请求超时(connect + write + read)默认没限制
final int callTimeout;
//连接超时(对应tcp connect())
final int connectTimeout;
//读取超时(对应TCP read())默认10s
final int readTimeout;
//写入超时(对应TCP write())默认10s
final int pingInterval;
//ping周期
final int writeTimeout;

线程资源管理层

这一层次的类只有Dispatcher一个。

  final Dispatcher dispatcher;

OkHttpClient.Buider会使用其的无参构造函数创建一个默认的实现,无参构造函数会使用内置的线程池来执行异步任务。

public Builder() {
    
    
  dispatcher = new Dispatcher();
  ...
}

Dispatcher主要是实现异步请求任务策略,负责分配异步线程资源,控制异步连接数,只覆盖线程资源层面的逻辑,往下的执行过程对其来说是透明的。对于同步任务,Dispatcher只是简单记录当前运行的任务实体(RealCall),并且是由RealCall主动注册和注销。
你可以通过OkHttpClient.Builder和Dispatvher有参构造函数来指定执行异步任务的线程池。

//这里出于演示目的,只是创建了一个简单的线程池,真正使用需要用户根据自己的应用场景配置自己的线程池。
Executor executor = Executors.newSingleThreadExecutor();
OkHttpClient client = new OkHttpClient
        .Builder()
        .dispatcher(new Dispatcher(executor))
        .build();

应用层协议(Http)实现

//用户自定义拦截器,默认为空,会被添加到Interceptor调用链的最前端
final List<Interceptor> interceptors;
//用户自定义拦截器,默认为空,拦截所有非WebSocket的请求和响应。
//该集合会被添加到Connect完成后和数据发送前的中间
final List<Interceptor> networkInterceptors;
//自定义CookieJar,系统默认只有一个空实现,如果用户想实现Cookie功能,需要自己实现该接口,并且设置到OKHttpClient中。
final CookieJar cookieJar;
//实现了Http协议的缓存规范,默认为空。
final @Nullable Cache cache;

连接池

//连接池
final ConnectionPool connectionPool;

ConnectionPool是一个finnal类,同时它并没有实现连接池的功能,而是委派给RealConnectionPool来实现:

public final class ConnectionPool {
    
    
	final RealConnectionPool delegate;
	//默认参数
	public ConnectionPool() {
    
    
	  this(5, 5, TimeUnit.MINUTES);
	}
	//用户可以通过该构造方法指定一些线程池的配置参数
	public ConnectionPool(int maxIdleConnections, long keepAliveDuration, TimeUnit timeUnit) {
    
    
	  this.delegate = new RealConnectionPool(maxIdleConnections, keepAliveDuration, timeUnit);
	}
	//下面三个方法都是通过委派给RealConnection实例完成
	public int idleConnectionCount() {
    
    
	  return delegate.idleConnectionCount();
	}
	...
}

ConnectionPool 虽然是不可扩展的,但是你可以通过这样的方式修改ConnectionPool 的默认参数:

OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
				//最大空闲连接数是10,空闲连接存活时间是15分钟
                .connectionPool(new ConnectionPool(10,15, TimeUnit.MINUTES))
                .build();

传输层

//代理服务设置,默认为空
final @Nullable Proxy proxy;
//代理选择器,默认为空
//对于Proxy和ProxySelector的使用,小伙伴可以参考JDK官方文档,机翻一下应该看懂也不难。
//https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html
final ProxySelector proxySelector;
//Socket工厂类,默认为DefaultSocketFactory。你可以自定义自己的SocketFacotry。
final SocketFactory socketFactory;
//SSLSocket工厂类,默认SSLSocketFactoryImpl,也可以自定义。
final SSLSocketFactory sslSocketFactory;
//SSL主机名验证
final HostnameVerifier hostnameVerifier;
//下面两个是对SSL证书的处理
final CertificateChainCleaner certificateChainCleaner;
final CertificatePinner certificatePinner;
//代理权限认证
final Authenticator proxyAuthenticator;
//代理权限认证
final Authenticator authenticator;
//DNS解析
final Dns dns;

内部使用类

static {
    
    
	//OKHttp内部类,主要代理了一些OKHttp重用的内部API,
	//方便后序OKHttp升级,如果后期某个API从语义上改变了,只需要修改Internal里面相应的代理方法即可
    Internal.instance = new Internal() {
    
    
    ...
    }
}

总结

到这里,我们就对OkHttpClient进行了一遍初略的了解,了解它到底有哪些属性,并对这些属性的作用进行了一个简单的归类,同时指出了哪些是可以自定义扩展和配置的。
在后面我们会对OkHttp其他的一些关键的实现类,进行详细的源码分析,如果文章有什么问题,也欢迎大家指出。

猜你喜欢

转载自blog.csdn.net/u012180773/article/details/112447355