OkHttp的整体架构大致可以分为以下几层:
Interface
(接口层):接受网络访问请求Protocol
(协议层):处理协议逻辑Connection
(连接层):管理网络连接,发送新的请求,接收服务器访问Cache
(缓存层):管理本地缓存I/O
(I/O层):实际数据读写实现Inteceptor
(拦截器层):拦截网络访问,插入拦截逻辑
Interface(接口层)
接收用户的网络访问请求(同步/异步),发起实际的网络访问。
OkHttpClient
是okhttp框架的客户端,用户使用okhttp进行各种设置,发起各种网络请求都是通过OkHttpClient完成的。每个OkHttpClient内部都维护了属于自己的任务队列,连接池,Cache,拦截器等,所以应该全局共享一个OkHttpClient实例。
Call
描述一个实际的访问请求,用户的每一个网络请求都是一个Call实例。Call本身是一个接口,实际执行过程中,okhttp会为每一个请求创建一个RealCall,每个RealCall
里面有一个AsyncCall
final class AsyncCall extends NamedRunnable {
private final Callback responseCallback;
private volatile AtomicInteger callsPerHost = new AtomicInteger(0);
AsyncCall(Callback responseCallback) {
super("OkHttp %s", redactedUrl());
this.responseCallback = responseCallback;
}
AtomicInteger callsPerHost() {
return callsPerHost;
}
void reuseCallsPerHostFrom(AsyncCall other) {
this.callsPerHost = other.callsPerHost;
}
String host() {
return originalRequest.url().host();
}
Request request() {
return originalRequest;
}
RealCall get() {
return RealCall.this;
}
/**
* Attempt to enqueue this async call on {@code executorService}. This will attempt to clean up
* if the executor has been shut down by reporting the call as failed.
*/
void executeOn(ExecutorService executorService) {
...
}
@Override protected void execute() {
boolean signalledCallback = false;
transmitter.timeoutEnter();
try {
Response response = getResponseWithInterceptorChain();
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 {
client.dispatcher().finished(this);
}
}
}
AsyncCall继承的NamedRunnable实现Runnable接口。
public abstract class NamedRunnable implements Runnable {
protected final String name;
public NamedRunnable(String format, Object... args) {
this.name = Util.format(format, args);
}
@Override public final void run() {
String oldName = Thread.currentThread().getName();
Thread.currentThread().setName(name);
try {
execute();
} finally {
Thread.currentThread().setName(oldName);
}
}
protected abstract void execute();
}
由此看出每一个Call都是一个线程,执行Call的过程就是执行其execute方法的过程。
Dispatcher
是okhttp的任务队列,其内部维护了一个线程池,当接收到一个Call时,Dispatcherf负责在线程池中找到空闲的线程并执行其execute方法。
Protocol(协议层)
OkHttp支持http1/http2/WebSocket协议,在3.7版本放弃了Spdy协议。鼓励开发者使用http2。
Connection(连接层)
在连接层中有一个连接池,统一管理所有的Socket连接,当用户新发起一个网络请求时,OkHttp会首先从连接池中查找是否有符合要求的连接,如果有则直接通过该连接发送网络请求,否则新创建一个网络连接。
RealConnection
描述一个物理Socket连接,连接池中维护多个RealConnection实例。由于HTTP2支持多路复用,一个RealConnection可以支持多个网络访问请求。
StreamAllocation
来描述一个实际的网络请求开销(从逻辑上一个Stream对应一个Call,但在实际网络请求过程中一个Call常常涉及到多次请求。如重定向,Authenticate等场景。所以准确地说,一个Stream对应一次请求,而一个Call对应一组有逻辑关联的Stream),一个RealConnection对应一个或多个StreamAllocation,所以StreamAllocation可以看做是RealConenction的计数器,当RealConnection的引用计数变为0,且长时间没有被其他请求重新占用就将被释放。
Cache(缓存层)
当用户的网络请求在本地已有符合要求的缓存时,okhttp会直接从缓存中返回结果,节省网络开销。
I/O(I/O层)
实际的数据读写,有高效的I/O库okio
Inteceptor(拦截器层)
提供了一个AOP(面向切向编程:涉及到众多模块的某一类问题进行统一管理)接口,方便用户可以切入到各个层面对网络访问进行拦截并执行相关逻辑。