OkHttp是有Square公司贡献一个处理网络请求的开源项目,是目前Android使用最广泛的网络框架,从Android4.4开始HttpURLConnection的底层也是采用Okhttp框架。
- 支持HTTP/2并允许对同一主机的所有请求共享一个套接字
- 通过连接池,减少了请求延迟
- 默认通过GZip压缩数据
- 响应缓存,避免重复请求网路
- 请求失败自动重试主机的其他Host-IP地址,自动重定向
请求流程
一次完整的请求时,必须使用其中的三个对象分别为:OkHttpClient,Request,Call
OkHttpClient
和Request
的创建可以使用提供的Builder(建造者模式)Call
则是把Request
交给OkHttpClient
之后,返回的一个准备完整并且待执行的请求体-
选择
execute
同步/enqueue
异步- 如果是
execute
同步,返回Response 响应对象,需要注意的是这里有会存在线程阻塞,需抛出throws IOException
- 选择是
enqueue
异步,返回Callback
接口并且实现-onFailure(Call call, IOException e)
和onResponse(Call call, Response response)
- 如果是
Dispatcher
分发起 和Interceptors
拦截器 是Okhttp的核心设计通过 Response 响应对象,进行解析拿取数据集
请求流程图
事例代码
String url = "http://wwww.xxxxx.com";
//1.构造OkHttpClient对象
OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
// .cache() 缓存设置
// .addInterceptor() 拦截器
// .sslSocketFactory() SSL设置
.build();
//2.构造Request对象
Request request = new Request.Builder()
.url(url)
// .post(new RequestBody()) Post请求体需要 RequestBody对象
.build();
//3.通过newCall返回请求
Call call = okHttpClient.newCall(request);
//4 - 1 同步请求
Response response = call.execute();
//4 - 2 异步请求
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d(TAG, "onFailure: ");
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d(TAG, "onResponse: " + response.body().string());
}
});
OkHttpClient
//默认建造 ... 等功能配置
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; //cookie
this.internalCache = okHttpClient.internalCache;
this.cache = okHttpClient.cache; //缓存
this.socketFactory = okHttpClient.socketFactory; //Socket配置
this.sslSocketFactory = okHttpClient.sslSocketFactory;//SSL/TLS
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; //心跳ping
}
Request
public static class Builder {
HttpUrl url;
String method;
Headers.Builder headers;
RequestBody body; //post请求体
Object tag;
public Builder() {
this.method = "GET";
this.headers = new Headers.Builder();
}
Builder(Request request) {
this.url = request.url;
this.method = request.method;
this.body = request.body;
this.tag = request.tag;
this.headers = request.headers.newBuilder();
}
//.....
}
Call
@Override
public Call newCall(Request request) {
//返回Call接口
return RealCall.newRealCall(this, request, false /* for web socket */);
}
static RealCall newRealCall(OkHttpClient client, Request originalRequest,boolean forWebSocket) {
// 直接new出Call的实现对象RealCall
RealCall call = new RealCall(client, originalRequest, forWebSocket);
call.eventListener = client.eventListenerFactory().create(call);
return call;
}
Call接口
package okhttp3;
import java.io.IOException;
//Call接口
public interface Call extends Cloneable {
Request request();
Response execute() throws IOException;
void enqueue(Callback responseCallback);
void cancel();
boolean isExecuted();
boolean isCanceled();
Call clone();
interface Factory {
Call newCall(Request request);
}
}
RealCall
final class RealCall implements Call {
//....
//同步请求
@Override
public Response execute() throws IOException {
//call只能执行一个请求
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
try {
//分发器
client.dispatcher().executed(this);
//拦截器(完成请求封装U回调) =》得到结果响应
Response result = getResponseWithInterceptorChain();
if (result == null) throw new IOException("Canceled");
return result;
} catch (IOException e) {
eventListener.callFailed(this, e);
throw e;
} finally {
//回调通知
client.dispatcher().finished(this);
}
}
@Override
public void enqueue(Callback responseCallback) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
//分发器
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
//一个请求任务, 其NamedRunnable类实现Runnable接口,是一个模版设计模式
final class AsyncCall extends NamedRunnable {
private final Callback responseCallback;
//接口回调
AsyncCall(Callback responseCallback) {
super("OkHttp %s", redactedUrl());
this.responseCallback = responseCallback;
}
String host() {
return originalRequest.url().host();
}
Request request() {
return originalRequest;
}
RealCall get() {
return RealCall.this;
}
@Override
protected void execute() {
boolean signalledCallback = false;
try {
//拦截器(完成请求封装U回调) =》得到结果响应
Response response = getResponseWithInterceptorChain();
if (retryAndFollowUpInterceptor.isCanceled()) {
signalledCallback = true;
responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
} else {
signalledCallback = true;
responseCallback.onResponse(RealCall.this, response);
}
} catch (IOException e) {
if (signalledCallback) {
// Do not signal the callback twice!
Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
} else {
eventListener.callFailed(RealCall.this, e);
responseCallback.onFailure(RealCall.this, e);
}
} finally {
//当执行完毕后, 1,从runing队列移除, 2,并且满足条件,在从ready迭代,Remove放到runing中...
client.dispatcher().finished(this);
}
}
}
}
Dispatcher 分发器
分发器就是来调配请求任务,内部会包含一个线程池,当异步请求时候,会将任务讲给线程池来执行。
public synchronized ExecutorService executorService() {
if (executorService == null) {
executorService = new ThreadPoolExecutor(
0, //核心线程数
Integer.MAX_VALUE, //最大线程
60, //空闲线程闲置时间
TimeUnit.SECONDS, //闲置时间单位
new SynchronousQueue(), //线程等待队列 这是SynchronousQueue,没有容量的高并发,主要是外部有对任务请求的的runing和reday操作,这里就不需要线程池的操作
Util.threadFactory("OkHttp Dispatcher", false)//线程创建工厂 Thread newThread(Runnable r);
);
}
return executorService;
}
俩种队列
-
running
执行队列 又分 存放同步runningSyncCalls
和 异步runningAsyncCalls
-
ready
等待队列(异步)Deque
readyAsyncCalls = new ArrayDeque<>()
-
**同步的分发器,直接add添加到 执行队列中 **
Deque
队列中...runningSyncCalls = new ArrayDeque<>();
- 异步的分发器会进行判断进入哪个队列中,running执行 还是 ready等待 队列中
synchronized void enqueue(AsyncCall call) {
//1、如果正在执行的请求小于64
//2、相同host的请求不能超过5个
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call); //正在执行的请求
executorService().execute(call); //线程池跑任务
} else {
readyAsyncCalls.add(call);
}
}
通过代码可以知晓,进入runningAsyncCalls
异步执行队列必须满足2个条件:
1. 如果正在执行的请求小于64 **考虑客户端请求压力**
2. 相同host的请求不能超过5个 **考虑服务器Host压力**
否则就进入readyAsyncCalls
等待队列
finished
移除当期执行完毕的队列,并且满足执行队列数目小于65,且同一Host中请求小于5才从ready队列取出放入runing队列。
/**
*
* @param calls 当期所诉执行队列 同步/异步
* @param call 泛型 同步RealCall 、 AsyncCall异步
* @param promoteCalls 是否从等待队列中取(目前只有异步有ready队列)
* @param
*/
private void finished(Deque calls, T call, boolean promoteCalls) {
int runningCallsCount;
Runnable idleCallback;
synchronized (this) {
//在runing执行队列移除当期队列,因为执行完毕了。
if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
if (promoteCalls) promoteCalls(); //取等待队列
runningCallsCount = runningCallsCount(); //同步+异步的正在执行任务数量
idleCallback = this.idleCallback;
}
//如果没有正在执行的任务,且idleCallback不为null,则回调通知空闲了
if (runningCallsCount == 0 && idleCallback != null) {
idleCallback.run();
}
}
/**
* 从ready获取任务放入running执行
*/
private void promoteCalls() {
if (runningAsyncCalls.size() >= maxRequests) return; // 执行队列数目里大于64,不取
if (readyAsyncCalls.isEmpty()) return; // 等待队列没有数据,不取
//迭代Ready队列
for (Iterator i = readyAsyncCalls.iterator(); i.hasNext(); ) {
AsyncCall call = i.next();
// 同一Host请求只能同时有5个
if (runningCallsForHost(call) < maxRequestsPerHost) {
i.remove();
runningAsyncCalls.add(call);
executorService().execute(call);
}
if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity.
}
}
Interceptor 拦截器
//拦截器集合 五大拦截器。有先后顺序(很重要)
Response getResponseWithInterceptorChain() throws IOException {
// 有序队列
List interceptors = new ArrayList<>();
interceptors.addAll(client.interceptors()); //自定义拦截器加入到集合
interceptors.add(RetryAndFollowUpInterceptor); //1、重定向拦截器
interceptors.add(new BridgeInterceptor(client.cookieJar()));//2、Hander责任连拦截器
interceptors.add(new CacheInterceptor(client.internalCache()));//3、缓存策略拦截器
interceptors.add(new ConnectInterceptor(client));//4、连接拦截器,与服务器TCP完成连接
if (!forWebSocket) {
interceptors.addAll(client.networkInterceptors()); //自定义拦截器,只对非网页的请求生效
}
interceptors.add(new CallServerInterceptor(forWebSocket));//5、与服务器通讯,封装请求数据与解析响应拦截器
Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
originalRequest, this, eventListener, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
return chain.proceed(originalRequest);
}
五大拦截器:
- RetryAndFollowUpInterceptor:负责失败重试以及重定向
- BridgeInterceptor:负责把用户构造的请求转换为发送给服务器的请求,把服务器返回的响应转换为对用户友好的响应。
- CacheInterceptor:负责读取缓存以及更新缓存
- ConnectInterceptor:连接拦截器,与服务器TCP完成连接
- CallServerInterceptor:与服务器通讯,封装请求数据与解析响应拦截器