为什么要学习源码:
作为一个中级工程师(自我定位),如何提高自己的代码能力是迫在眉睫的需求,阅读源码好处就不多说了,可以提高架构能力,阅读优秀的可以减少很多学习上的弯路。
源码的选择:
直接阅读Android的源码,对于学习Android的运行机制有好处,但是Android是一个重量级的操作系统,阅读源码只能从点上去逐渐了解某个机制的细节,要完全阅读Android操作系统,几乎是不可能的事情。所以选择学习从Okhttp这个近年来火的一塌糊涂的网络框架开始。
阅读的顺序:
笔者入行较浅,本博客实际上为不断学习的过程,在学习过程中出现的错误,还望不吝指正。
对于OkHttp的学习,我们从OkHttpClient这个用户最熟悉的类开始向下挖掘。今天先对其做个概览:
public class OkHttpClient
implements Cloneable
{
// 默认的协议
private static final List<Protocol> DEFAULT_PROTOCOLS = Util.immutableList(new Protocol[] { Protocol.HTTP_2, Protocol.SPDY_3, Protocol.HTTP_1_1 });
/* 默认的连接规范
1.MODERN_TLS 是连接到最新的HTTPS服务器的安全配置。
2.COMPATIBEL_TLS 是连接到过时的HTTPS服务器的安全配置。
3.CLEARTEXT 是用于http://开头的URL的非安全配置。
*/
private static final List<ConnectionSpec> DEFAULT_CONNECTION_SPECS = Util.immutableList(new ConnectionSpec[] { ConnectionSpec.MODERN_TLS, ConnectionSpec.COMPATIBLE_TLS, ConnectionSpec.CLEARTEXT });
//默认SSLSocket工厂
private static SSLSocketFactory defaultSslSocketFactory;
//路由服务器
private final RouteDatabase routeDatabase;
//分发器
private Dispatcher dispatcher;
//代理
private Proxy proxy;
//协议列表
private List<Protocol> protocols;
//连接规范
private List<ConnectionSpec> connectionSpecs;
static
{ //见Internal类
Internal.instance = new Internal()
{
public void addLenient(Headers.Builder builder, String line)
{
builder.addLenient(line);
}
public void addLenient(Headers.Builder builder, String name, String value)
{
builder.addLenient(name, value);
}
public void setCache(OkHttpClient client, InternalCache internalCache)
{
client.setInternalCache(internalCache);
}
public InternalCache internalCache(OkHttpClient client)
{
return client.internalCache();
}
public boolean connectionBecameIdle(ConnectionPool pool, RealConnection connection)
{
return pool.connectionBecameIdle(connection);
}
public RealConnection get(ConnectionPool pool, Address address, StreamAllocation streamAllocation)
{
return pool.get(address, streamAllocation);
}
public void put(ConnectionPool pool, RealConnection connection)
{
pool.put(connection);
}
public RouteDatabase routeDatabase(ConnectionPool connectionPool)
{
return connectionPool.routeDatabase;
}
public void callEnqueue(Call call, Callback responseCallback, boolean forWebSocket)
{
call.enqueue(responseCallback, forWebSocket);
}
public StreamAllocation callEngineGetStreamAllocation(Call call)
{
return call.engine.streamAllocation;
}
public void apply(ConnectionSpec tlsConfiguration, SSLSocket sslSocket, boolean isFallback)
{
tlsConfiguration.apply(sslSocket, isFallback);
}
public HttpUrl getHttpUrlChecked(String url)
throws MalformedURLException, UnknownHostException
{
return HttpUrl.getChecked(url);
}
};
}
//拦截机
private final List<Interceptor> interceptors = new ArrayList();
//网络拦截机
private final List<Interceptor> networkInterceptors = new ArrayList();
//代理选择器
private ProxySelector proxySelector;
//CookieHandler
private CookieHandler cookieHandler;
//InternalCache
private InternalCache internalCache;
//缓存
private Cache cache;
//socket工厂
private SocketFactory socketFactory;
//sslSocket工厂
private SSLSocketFactory sslSocketFactory;
//主机名验证着
private HostnameVerifier hostnameVerifier;
//证书
private CertificatePinner certificatePinner;
//作者
private Authenticator authenticator;
//连接池
private ConnectionPool connectionPool;
//DNS
private Dns dns;
//跟随ssl更改
private boolean followSslRedirects = true;
//跟随更改
private boolean followRedirects = true;
//重连失败
private boolean retryOnConnectionFailure = true;
//连接超时时间
private int connectTimeout = 10000;
//读取超时时间
private int readTimeout = 10000;
//写超时时间
private int writeTimeout = 10000;
public OkHttpClient()
{
//新建路由数据库
this.routeDatabase = new RouteDatabase();
//新建分发器
this.dispatcher = new Dispatcher();
}
private OkHttpClient(OkHttpClient okHttpClient)
{
this.routeDatabase = okHttpClient.routeDatabase;
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.cookieHandler = okHttpClient.cookieHandler;
this.cache = okHttpClient.cache;
this.internalCache = (this.cache != null ? this.cache.internalCache : okHttpClient.internalCache);
this.socketFactory = okHttpClient.socketFactory;
this.sslSocketFactory = okHttpClient.sslSocketFactory;
this.hostnameVerifier = okHttpClient.hostnameVerifier;
this.certificatePinner = okHttpClient.certificatePinner;
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;
}
public void setConnectTimeout(long timeout, TimeUnit unit)
{
if (timeout < 0L) {
throw new IllegalArgumentException("timeout < 0");
}
if (unit == null) {
throw new IllegalArgumentException("unit == null");
}
long millis = unit.toMillis(timeout);
if (millis > 2147483647L) {
throw new IllegalArgumentException("Timeout too large.");
}
if ((millis == 0L) && (timeout > 0L)) {
throw new IllegalArgumentException("Timeout too small.");
}
this.connectTimeout = ((int)millis);
}
public int getConnectTimeout()
{
return this.connectTimeout;
}
public void setReadTimeout(long timeout, TimeUnit unit)
{
if (timeout < 0L) {
throw new IllegalArgumentException("timeout < 0");
}
if (unit == null) {
throw new IllegalArgumentException("unit == null");
}
long millis = unit.toMillis(timeout);
if (millis > 2147483647L) {
throw new IllegalArgumentException("Timeout too large.");
}
if ((millis == 0L) && (timeout > 0L)) {
throw new IllegalArgumentException("Timeout too small.");
}
this.readTimeout = ((int)millis);
}
public int getReadTimeout()
{
return this.readTimeout;
}
public void setWriteTimeout(long timeout, TimeUnit unit)
{
if (timeout < 0L) {
throw new IllegalArgumentException("timeout < 0");
}
if (unit == null) {
throw new IllegalArgumentException("unit == null");
}
long millis = unit.toMillis(timeout);
if (millis > 2147483647L) {
throw new IllegalArgumentException("Timeout too large.");
}
if ((millis == 0L) && (timeout > 0L)) {
throw new IllegalArgumentException("Timeout too small.");
}
this.writeTimeout = ((int)millis);
}
public int getWriteTimeout()
{
return this.writeTimeout;
}
public OkHttpClient setProxy(Proxy proxy)
{
this.proxy = proxy;
return this;
}
public Proxy getProxy()
{
return this.proxy;
}
public OkHttpClient setProxySelector(ProxySelector proxySelector)
{
this.proxySelector = proxySelector;
return this;
}
public ProxySelector getProxySelector()
{
return this.proxySelector;
}
public OkHttpClient setCookieHandler(CookieHandler cookieHandler)
{
this.cookieHandler = cookieHandler;
return this;
}
public CookieHandler getCookieHandler()
{
return this.cookieHandler;
}
void setInternalCache(InternalCache internalCache)
{
this.internalCache = internalCache;
this.cache = null;
}
InternalCache internalCache()
{
return this.internalCache;
}
public OkHttpClient setCache(Cache cache)
{
this.cache = cache;
this.internalCache = null;
return this;
}
public Cache getCache()
{
return this.cache;
}
public OkHttpClient setDns(Dns dns)
{
this.dns = dns;
return this;
}
public Dns getDns()
{
return this.dns;
}
public OkHttpClient setSocketFactory(SocketFactory socketFactory)
{
this.socketFactory = socketFactory;
return this;
}
public SocketFactory getSocketFactory()
{
return this.socketFactory;
}
public OkHttpClient setSslSocketFactory(SSLSocketFactory sslSocketFactory)
{
this.sslSocketFactory = sslSocketFactory;
return this;
}
public SSLSocketFactory getSslSocketFactory()
{
return this.sslSocketFactory;
}
public OkHttpClient setHostnameVerifier(HostnameVerifier hostnameVerifier)
{
this.hostnameVerifier = hostnameVerifier;
return this;
}
public HostnameVerifier getHostnameVerifier()
{
return this.hostnameVerifier;
}
public OkHttpClient setCertificatePinner(CertificatePinner certificatePinner)
{
this.certificatePinner = certificatePinner;
return this;
}
public CertificatePinner getCertificatePinner()
{
return this.certificatePinner;
}
public OkHttpClient setAuthenticator(Authenticator authenticator)
{
this.authenticator = authenticator;
return this;
}
public Authenticator getAuthenticator()
{
return this.authenticator;
}
public OkHttpClient setConnectionPool(ConnectionPool connectionPool)
{
this.connectionPool = connectionPool;
return this;
}
public ConnectionPool getConnectionPool()
{
return this.connectionPool;
}
public OkHttpClient setFollowSslRedirects(boolean followProtocolRedirects)
{
this.followSslRedirects = followProtocolRedirects;
return this;
}
public boolean getFollowSslRedirects()
{
return this.followSslRedirects;
}
public void setFollowRedirects(boolean followRedirects)
{
this.followRedirects = followRedirects;
}
public boolean getFollowRedirects()
{
return this.followRedirects;
}
public void setRetryOnConnectionFailure(boolean retryOnConnectionFailure)
{
this.retryOnConnectionFailure = retryOnConnectionFailure;
}
public boolean getRetryOnConnectionFailure()
{
return this.retryOnConnectionFailure;
}
RouteDatabase routeDatabase()
{
return this.routeDatabase;
}
public OkHttpClient setDispatcher(Dispatcher dispatcher)
{
if (dispatcher == null) {
throw new IllegalArgumentException("dispatcher == null");
}
this.dispatcher = dispatcher;
return this;
}
public Dispatcher getDispatcher()
{
return this.dispatcher;
}
public OkHttpClient setProtocols(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 List<Protocol> getProtocols()
{
return this.protocols;
}
public OkHttpClient setConnectionSpecs(List<ConnectionSpec> connectionSpecs)
{
this.connectionSpecs = Util.immutableList(connectionSpecs);
return this;
}
public List<ConnectionSpec> getConnectionSpecs()
{
return this.connectionSpecs;
}
public List<Interceptor> interceptors()
{
return this.interceptors;
}
public List<Interceptor> networkInterceptors()
{
return this.networkInterceptors;
}
public Call newCall(Request request)
{
return new Call(this, request);
}
public OkHttpClient cancel(Object tag)
{
getDispatcher().cancel(tag);
return this;
}
OkHttpClient copyWithDefaults()
{
OkHttpClient result = new OkHttpClient(this);
if (result.proxySelector == null) {
result.proxySelector = ProxySelector.getDefault();
}
if (result.cookieHandler == null) {
result.cookieHandler = CookieHandler.getDefault();
}
if (result.socketFactory == null) {
result.socketFactory = SocketFactory.getDefault();
}
if (result.sslSocketFactory == null) {
result.sslSocketFactory = getDefaultSSLSocketFactory();
}
if (result.hostnameVerifier == null) {
result.hostnameVerifier = OkHostnameVerifier.INSTANCE;
}
if (result.certificatePinner == null) {
result.certificatePinner = CertificatePinner.DEFAULT;
}
if (result.authenticator == null) {
result.authenticator = AuthenticatorAdapter.INSTANCE;
}
if (result.connectionPool == null) {
result.connectionPool = ConnectionPool.getDefault();
}
if (result.protocols == null) {
result.protocols = DEFAULT_PROTOCOLS;
}
if (result.connectionSpecs == null) {
result.connectionSpecs = DEFAULT_CONNECTION_SPECS;
}
if (result.dns == null) {
result.dns = Dns.SYSTEM;
}
return result;
}
private synchronized SSLSocketFactory getDefaultSSLSocketFactory()
{
if (defaultSslSocketFactory == null) {
try
{
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, null, null);
defaultSslSocketFactory = sslContext.getSocketFactory();
}
catch (GeneralSecurityException e)
{
throw new AssertionError();
}
}
return defaultSslSocketFactory;
}
public OkHttpClient clone()
{
return new OkHttpClient(this);
}
以上贴出了OkhttpClinet这个类的全部源码,这个类中,分析每一个熟悉,从而了解Okhttp的所包含的机制,如SSL、路由、分发器、协议、代理、连接规范等。这之中每一个机制细细分解都是很深的内容,而我们要看的重点,是从OkhttpClient的使用入手,newCall(Request request)方法。该方法返回的类是Call.class。所以下一步我们研究的是Call这个类。