基于HttpClient进行封装的网络请求库,由于Android在6.0的时候已经不再推荐使用HttpClient了,所以这个库也就不适合作为我们网络框架的选择了。
13年Google发布的网络框架,是基于HttpUrlConnection进行网络请求的轻量级框架,扩展性好,可支持HttpClient/HttpUrlConnection/OKHttp。缺点有二,其一是不支持同步请求。其二是不支持大数据量操作,比如文件上传下载。
它比较适合轻量级网络交互,网络请求频繁,传输数据量小的场景。
为什么Volley不适合大数量的传输操作呢?
Volley中为了提高请求处理的速度,采用了ByteArrayPool进行内存中的数据存储的,如果下载大量的数据,这个存储空间就会溢出,所以不适合大量的数据,但是由于他的这个存储空间是内存中分配的,当存储的时候优是从ByteArrayPool中取出一块已经分配的内存区域, 不必每次存数据都要进行内存分配,而是先查找缓冲池中有无适合的内存区域,如果有,直接拿来用,从而减少内存分配的次数 ,所以他比较适合大量的数据量少的网络数据交互情况。
是高性能的http库,支持同步、异步,而且实现了http2、websocket协议,api很简洁易用,和volley一样实现了http协议的缓存。picasso就是利用okhttp的缓存机制实现其文件缓存,实现的很优雅,很正确,反例就是UIL(universal image loader),自己做的文件缓存,而且不遵守http缓存机制。另外在Android6.0的源码里,已经看到HttpUrlConnection被替换成OKHttp了。
OKHttp的再次封装,通过注解配置请求,包括请求方法、请求参数、请求头、返回值等。可以搭配多种Converter将获得的数据解析&序列化。简单易用;代码简化;解耦彻底,职责细分;易与和rxjava结合使用。
分析源码前,从使用入手,追踪调用代码。使用如下:
// 通过Builder模式创建OkHttpClient对象
OkHttpClient client = new OkHttpClient.Builder().build();
// 通过Builder模式创建Request对象
Request request = new Request.Builder().url("").build();
// 创建Call对象
Call call = client.newCall(request);
try {
// 同步请求
call.execute();
} catch (IOException e) {
}
// 异步请求
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});
// OKHttpClient类的静态内部类Builder
public static final class Builder {
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;
}
// build方法
public OkHttpClient build() {
// 创建一个OKHttpClient,并把当前的Builder对象传进去
return new OkHttpClient(this);
}
}
// OkHttpClient的构造方法
// 其实就是把Builder里的值赋值到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;
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;
}
// Request类的静态内部类Builder类
// 和OKHttpClient没有什么不同,都是基于构造者模式来设置参数
// Request要设置的参数包括URL、Method、Header、Body请求相关的
public static class Builder {
HttpUrl url;
String method;
Headers.Builder headers;
RequestBody body;
Object tag;
public Builder() {
this.method = "GET";
this.headers = new Headers.Builder();
}
public Builder url(HttpUrl url) {
if (url == null) throw new NullPointerException("url == null");
this.url = url;
return this;
}
}
// OKHttpClient类的newCall方法
@Override public Call newCall(Request request) {
return new RealCall(this, request, false /* for web socket */);
}
// RealCall类
final class RealCall implements Call {
RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
final EventListener.Factory eventListenerFactory = client.eventListenerFactory();
this.client = client;
this.originalRequest = originalRequest;
this.forWebSocket = forWebSocket;
this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket);
// TODO(jwilson): this is unsafe publication and not threadsafe.
this.eventListener = eventListenerFactory.create(this);
}
}
// RealCall类的excute方法
@Override public Response execute() throws IOException {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
try {
// (1)最终调用Dispatcher类的executed方法
client.dispatcher().executed(this);
// (2)拦截器,核心
Response result = getResponseWithInterceptorChain();
if (result == null) throw new IOException("Canceled");
return result;
} finally {
// (3)最终调用Dispatcher的finished方法
client.dispatcher().finished(this);
}
}
public final class Dispatcher {
// 最大并发的请求数
private int maxRequests = 64;
// 每个host最大的请求数
private int maxRequestsPerHost = 5;
// 线程池
private @Nullable ExecutorService executorService;
// 双向队列,存储还未运行的异步队列
private final Deque readyAsyncCalls = new ArrayDeque<>();
// 双向队列,存储正在运行的异步任务
private final Deque runningAsyncCalls = new ArrayDeque<>();
// 双向队列,存储正在运行的同步任务
private final Deque runningSyncCalls = new ArrayDeque<>();
// 上面(1)处最终调用的是这个方法,没做别的事,
// 就是把这个任务添加到正在运行的同步任务双向队列里
synchronized void executed(RealCall call) {
runningSyncCalls.add(call);
}
}
(2)和(3)在下面的异步调用源码处统一分析
// RealCall类的enqueue方法
@Override public void enqueue(Callback responseCallback) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
// 最终调用Dispatcher的enqueue方法
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
public final class Dispatcher {
// 最大并发的请求数
private int maxRequests = 64;
// 每个host最大的请求数
private int maxRequestsPerHost = 5;
// 线程池
private @Nullable ExecutorService executorService;
// 双向队列,存储还未运行的异步队列
private final Deque readyAsyncCalls = new ArrayDeque<>();
// 双向队列,存储正在运行的异步任务
private final Deque runningAsyncCalls = new ArrayDeque<>();
// 双向队列,存储正在运行的同步任务
private final Deque runningSyncCalls = new ArrayDeque<>();
// 异步调用的方法
synchronized void enqueue(AsyncCall call) {
// 运行的异步任务小于最大的并发请求数
// 并且,同一个主机的请求数小于5,也就是同时请求同一个域名的最大并发数是5
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
// 把任务添加到正在运行的异步队列里
runningAsyncCalls.add(call);
// 调用线程池的execute方法,把call放进去
executorService().execute(call);
} else {
// 把任务添加到未运行的异步队列里
readyAsyncCalls.add(call);
}
}
}
// AsyncCall类实现了Runnable
// 所以线程池回调就是这个execute方法
final class AsyncCall extends NamedRunnable {
@Override
protected void execute() {
boolean signalledCallback = false;
try {
// 上面(2)所说的拦截器方法,核心
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 {
responseCallback.onFailure(RealCall.this, e);
}
} finally {
// 上面(3)所说的方法
client.dispatcher().finished(this);
}
}
}
// (2)的方法实现
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List interceptors = new ArrayList<>();
// 我们平常设置的拦截器,就是在这
interceptors.addAll(client.interceptors());
// 重试和重定向拦截器,主要负责网络失败重连。
interceptors.add(retryAndFollowUpInterceptor);
// 桥拦截器,负责把用户构造的请求转换为发送给服务器的请求,把服务器返回的响应转换为对用户友好的响应
// 比如在Request阶段配置用户信息,并添加一些请求头。在Response阶段,进行gzip解压
interceptors.add(new BridgeInterceptor(client.cookieJar()));
// 缓存拦截器,OKHttp有自己的缓存体系,这个拦截器用于读取和更新缓存
interceptors.add(new CacheInterceptor(client.internalCache()));
// 向服务器建立连接的拦截器
interceptors.add(new ConnectInterceptor(client));
if (!forWebSocket) {
interceptors.addAll(client.networkInterceptors());
}
// 最后这个是,向服务器发送数据进行网络请求的拦截器
interceptors.add(new CallServerInterceptor(forWebSocket));
Interceptor.Chain chain = new RealInterceptorChain(
interceptors, null, null, null, 0, originalRequest);
// 调用RealInterceptorChain的proceed方法
return chain.proceed(originalRequest);
}
// RealInterceptorChain类
public final class RealInterceptorChain implements Interceptor.Chain {
// proceed方法
public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
RealConnection connection) throws IOException {
if (index >= interceptors.size()) throw new AssertionError();
calls++;
// If we already have a stream, confirm that the incoming request will use it.
if (this.httpCodec != null && !this.connection.supportsUrl(request.url())) {
throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
+ " must retain the same host and port");
}
// If we already have a stream, confirm that this is the only call to chain.proceed().
if (this.httpCodec != null && calls > 1) {
throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
+ " must call proceed() exactly once");
}
// Call the next interceptor in the chain.
// 又创建了下一个的Chain对象,下标的初始值是index+1
RealInterceptorChain next = new RealInterceptorChain(
interceptors, streamAllocation, httpCodec, connection, index + 1, request);
// 获取第index个拦截器,执行这个拦截器的intercept方法
// 我们假设目前index=0,即将执行retryAndFollowUpInterceptor的intercept方法
Interceptor interceptor = interceptors.get(index);
Response response = interceptor.intercept(next);
// Confirm that the next interceptor made its required call to chain.proceed().
if (httpCodec != null && index + 1 < interceptors.size() && next.calls != 1) {
throw new IllegalStateException("network interceptor " + interceptor
+ " must call proceed() exactly once");
}
// Confirm that the intercepted response isn't null.
if (response == null) {
throw new NullPointerException("interceptor " + interceptor + " returned null");
}
return response;
}
}
// 网络重试重定向的拦截器
public final class RetryAndFollowUpInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
...
...
Response response = null;
boolean releaseConnection = true;
try {
// 这里的chain就是上面创建的下一个的Chain对象,因此又回到上面的proceed方法
// 责任链模式实现了循环的调用不同的拦截器
response = ((RealInterceptorChain) chain).proceed(request, streamAllocation, null, null);
releaseConnection = false;
} catch (RouteException e) {
}
}
}
getResponseWithInterceptorChain方法, 可以看出真正请求执行的就在这一块, 根据责任链的设计思想, 将操作分开进行处理。
// 接着来看看上面说的(3)
// Dispatcher类
/** Used by {@code AsyncCall#run} to signal completion. */
void finished(AsyncCall call) {
finished(runningAsyncCalls, call, true);
}
// finished方法,异步的情况下,promoteCalls=true
private void finished(Deque calls, T call, boolean promoteCalls) {
int runningCallsCount;
Runnable idleCallback;
synchronized (this) {
// 把任务从双向队列里移除
if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
// 如果是异步任务,就会执行promoteCalls方法
if (promoteCalls) promoteCalls();
runningCallsCount = runningCallsCount();
idleCallback = this.idleCallback;
}
if (runningCallsCount == 0 && idleCallback != null) {
idleCallback.run();
}
}
// promoteCalls方法,这个方法实际上作用就是从等待队列里拿任务出来去执行
private void promoteCalls() {
if (runningAsyncCalls.size() >= maxRequests) return; // Already running max capacity.
if (readyAsyncCalls.isEmpty()) return; // No ready calls to promote.
// 遍历等待队列
for (Iterator i = readyAsyncCalls.iterator(); i.hasNext(); ) {
AsyncCall call = i.next();
// 判断同一个域名的请求数是否小于5
if (runningCallsForHost(call) < maxRequestsPerHost) {
// 从等待队列里移除这个任务
i.remove();
// 添加到运行中的队列
runningAsyncCalls.add(call);
// 放到线程池里执行
executorService().execute(call);
}
if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity.
}
}