本文,将对Okhttp
整体流程进行分析.
本文若无特殊说明,采用的okhttp
版本为 3.10.0
一.OkHttpClient分析
创建 OkHttpClient
实例的两种方式:
代码片1
OkHttpClient okHttpClient = new OkHttpClient();
OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
我们先研究第一种构造方式,也是默认的方式,我们点击OkHttpClient方法进去:
OkHttpClient.class
代码片2
public OkHttpClient() {
this(new Builder());
}
发现是一个类构造方法,this
其实就是指的是OkHttpClient
,也就是如下方法:
OkHttpClient.class
代码片3
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;
//删除多行代码
}
然后顺理成章的看一下new Builder()
方法
OkHttpClient.class
代码片4
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;
}
上述代码是做一些初始化配置.
现在来看另一个种构造方式:
OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
点开build()
方法,代码如下:
OkHttpClient.class
代码片5
public OkHttpClient build() {
return new OkHttpClient(this);
}
这里需要我们注意的是Builder
它是静态内部类.
上面讲到了OkHttpClient
的两种构造方式,通过查看源码,两种方式的配置是相同的,下面具体看一下到底配置了什么(即代码片4):
具体的配置内容,在下面代码中已经注释.
OkHttpClient.class
代码片6
public Builder() {
dispatcher = new Dispatcher(); //调度器,执行异步请求时的策略
protocols = DEFAULT_PROTOCOLS; //OKHTTP实现的协议LIST
connectionSpecs = DEFAULT_CONNECTION_SPECS; //TLS版本与连接协议
eventListenerFactory = EventListener.factory(EventListener.NONE); //监听器
proxySelector = ProxySelector.getDefault(); //代理选择器
cookieJar = CookieJar.NO_COOKIES; //cookie
socketFactory = SocketFactory.getDefault(); //socket 工厂
hostnameVerifier = OkHostnameVerifier.INSTANCE; //主机name验证
certificatePinner = CertificatePinner.DEFAULT;
proxyAuthenticator = Authenticator.NONE; //代理验证
authenticator = Authenticator.NONE; //验证
connectionPool = new ConnectionPool(); //连接池
dns = Dns.SYSTEM; //dns域名
followSslRedirects = true; //安全套接层重定向
followRedirects = true; //本地重定向
retryOnConnectionFailure = true; //错误重连
connectTimeout = 10_000; //connect超时
readTimeout = 10_000; //read超时
writeTimeout = 10_000; //write超时
pingInterval = 0; //ping超时
}
二.Request初始化
当我们构建完OkHttpClient
对象,需要构造Request
对象,构造方式如下:
1.Get请求:
Request request = new Request.Builder()
.url("https://www.wanandroid.com/article/list/1/json")
.get()//默认就是GET请求,可以不写
.build();
2.Post请求
拿POST
提交表单请求,这时就需要声明一个RequestBody
对象了
RequestBody requestBody = new FormBody.Builder()
.add("username", "weibuzudao")
.add("password", "123456")
.build();
Request request = new Request.Builder()
.url("https://www.wanandroid.com/user/login")
.post(requestBody)
.build();
看到上面代码是不是很熟悉?和OkHttpClient
很相似, 没错 Request
的构建也是Builder
模式!
我们点击Request
源码进去,果然 其中有静态的Builder
内部类:
Request.class
代码片7
public static class Builder {
HttpUrl url;
String method;
Headers.Builder headers;
RequestBody body;
//这里配置默认的参数
public Builder() {
this.method = "GET"; //默认是GET请求
this.headers = new Headers.Builder();
}
//这里通过另外一个Request配置参数
Builder(Request request) {
this.url = request.url;
this.method = request.method;
//...
}
//省略部分代码
// 配置完参数后,通过Builder的参数创建一个Request
public Request build() {
if (url == null) throw new IllegalStateException("url == null");
return new Request(this);
}
}
从代码看到了 如果没有声明,默认是Get
请求 this.method = "GET"
,至于url
等字段需要我们自己去配置:
HttpUrl
请求访问的url
,可以传String
与URL
具体方法如下:
Request.class
代码片8
public Builder url(HttpUrl url) {
if (url == null) throw new NullPointerException("url == null");
this.url = url;
return this;
}
/**
* Sets the URL target of this request.
*
* @throws IllegalArgumentException if {@code url} is not a valid HTTP or HTTPS URL. Avoid this
* exception by calling {@link HttpUrl#parse}; it returns null for invalid URLs.
*/
public Builder url(String url) {
if (url == null) throw new NullPointerException("url == null");
// Silently replace web socket URLs with HTTP URLs.
if (url.regionMatches(true, 0