前言
okhttp是我们安卓中运用最多的网络请求框架了,它的优势有很多,如支持HTTP2,SPDY,GZIP压缩,复用连接池提升效率等。
-
1.简单使用
//异步请求
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder().url("https://www.baidu.com").build();
okHttpClient.newCall(request1).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {}
@Override
public void onResponse(Call call, Response response) throws IOException {}
});
//同步
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder().url("https://www.baidu.com").build();
try {
Response response = okHttpClient.newCall(request).execute();
} catch (IOException e) {
e.printStackTrace();
}
-
2.OkHttpClient 分析
public OkHttpClient() {
this(new Builder());
}
public static final class Builder {
Dispatcher dispatcher;
@Nullable Proxy proxy;
List<Protocol> protocols;
List<ConnectionSpec> connectionSpecs;
final List<Interceptor> interceptors = new ArrayList<>();
final List<Interceptor> networkInterceptors = new ArrayList<>();
EventListener.Factory eventListenerFactory;
ProxySelector proxySelector;
CookieJar cookieJar;
@Nullable Cache cache;
省略若干.....
- okhttpClient里有个静态内部类Builder,这里运用了Builder设计模式同步builder动态构建出一些常用的参数,如我们常见的connectTimeout,readTimeout,writeTimeout,Cache,我们自定义的拦截器等。
/**
* Prepares the {@code request} to be executed at some point in the future.
*/
@Override public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}
newCall 方法是其中最重要的一个方法,通过我们传入的request来发起请求的。
RealCall是Call的实现类,方法里通过newRealCall方法把okhttpclient和request传了过去,返回了一个RealCall对象,然后我们通过该对象来发起同步或异步请求。
-
3.Dispatcher分析
上面我们收到RealCall 是用来发起请求的,发起请求就不得不提到一个类Dispatcher
这个类是在我们构建OkhttpClient的时候初始化的,是okhttpclient的成员
这个类用来管理所有同步或异步请求的,它还有发起异步请求的功能
//用来处理异步请求的线程池
private @Nullable ExecutorService executorService;
//待请求的异步任务队列
private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();
// 正在请求的异步任务队列
private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();
//正在请求的同步任务队列
private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();
......
//SynchronousQueue是一个内部只能包含一个元素的队列。插入元素到队列的线程被阻塞,直到另一个线程从队列中获取了队列中存储的元素。同样,如果线程尝试获取元素并且当前不存在任何元素,则该线程将被阻塞,直到线程将元素插入队列。
public synchronized ExecutorService executorService() {
if (executorService == null) {
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
}
return executorService;
}
- 这里用到的线程池核心线程为0,非核心线程数量为无限,闲置时间为60s
//同步
synchronized void executed(RealCall call) {
runningSyncCalls.add(call);
}
//异步
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
Dispatcher中有二个重要的方法,其中executed方法比较简单是直接把传入的请求加到同步队列中
enqueue方法会判断正在执行的请求是否小于64并且同一个host的请求是否小于5,这里传入的AsyncCall 实则为一个Runnable对象,满足条件就把它加入到请求队列并调用线程池执行它
否则就把它加入到等待队列中
-
4.RealCall 分析
上面我们收到RealCall 是用来发起请求的,它发起请求主要有如下二个方法
//同步
@Override public Response execute() throws IOException {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
try {
client.dispatcher().executed(this);
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));
}
- execute方法调用我们上面提到的dispatcher的executed方法,把call加到同步队列
- 执行getResponseWithInterceptorChain()来获取Response
- enqueue也是调用的dispatcher执行的enqueue方法
- 上面我们分析的enqueue方法,AsyncCall是一个Runnable由dispatcher里面的线程池执行它
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 {
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);
LogUtils.LogE("onFailure2");
}
} finally {
client.dispatcher().finished(this);
}
}
}
- 可以看到里面的execute的方法最终也是调用了RealCall方法里面的getResponseWithInterceptorChain()方法来得到Response,所以getResponseWithInterceptorChain是最终执行请求得到response的方法
private void promoteCalls() {
if (runningAsyncCalls.size() >= maxRequests) return; // Already running max capacity.
if (readyAsyncCalls.isEmpty()) return; // No ready calls to promote.
for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
AsyncCall call = i.next();
if (runningCallsForHost(call) < maxRequestsPerHost) {
i.remove();
runningAsyncCalls.add(call);
executorService().execute(call);
}
if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity.
}
}
- 这里简要说下client.dispatcher().finished(this)这个方法,它执行的是dispatcher里面的finished方法,它会把执行完成的call从正在请求的队列中移除并且会执行promoteCalls方法把readyAsyncCalls等待的异步请求中移动到runningAsyncCalls,并且调用线程池执行它
- 这样就保证了异步的请求有序的进行
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List<Interceptor> interceptors = new ArrayList<>();
interceptors.addAll(client.interceptors());
interceptors.add(retryAndFollowUpInterceptor);
interceptors.add(new BridgeInterceptor(client.cookieJar()));
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, this, eventListener, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
return chain.proceed(originalRequest);
}
这里就是okhttp最核心的地方了,首先创建了一个Interceptor的集合
Interceptor就是拦截器的意思,这里主要有retryAndFollowUpInterceptor,BridgeInterceptor,CacheInterceptor,ConnectInterceptor,CallServerInterceptor五个主要的拦截器
retryAndFollowUpInterceptor负责断线重连
BridgeInterceptor负责请求头的一些参数构建以及gzip压缩处理
CacheInterceptor负责okhttp缓存相关的操作
ConnectInterceptor负责建立socket链路连接,里面定义了连接池复用连接等
CallServerInterceptor负责发送请求获取响应
RealInterceptorChain是用来串联这些拦截器让它们各司其职,调用proceed方法完成请求
-
5.RealInterceptorChain分析
public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
RealConnection connection) throws IOException {
if (index >= interceptors.size()) throw new AssertionError();
calls++;
....省略若干代码
RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
writeTimeout);
Interceptor interceptor = interceptors.get(index);
Response response = interceptor.intercept(next);
.....省略若干代码
return response;
}
可以看到proceed方法中又创建了一个RealInterceptorChain把interceptors集合以及 index + 1传了进去。
然后通过index获取interceptors集合中的拦截器最后调用intercept方法并且传入了新创建的RealInterceptorChain 。
之后各个拦截器里面又调用同样的proceed方法只是index及有些参数不同,这样就完成了每个拦截器的顺序执行,这样的方式其实是运用到了责任链模式。
-
看下具体流程图
好了这就是整体的源码流程,下篇我们具体分析每个拦截器都来干了什么。