我们先来看下OkHttp的两个使用方法
同步:
//同步执行方法,不应该在UI线程使用
response = client.newCall(request).execute();
//异步方法
response = client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
}
});
让我们进入newCall一探究竟~
/**
* 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 */);
}
static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
// Safely publish the Call instance to the EventListener.
RealCall call = new RealCall(client, originalRequest, forWebSocket);
call.eventListener = client.eventListenerFactory().create(call);
return call;
}
可以看到返回了一个RealCall对象,接下来继续看RealCall是个什么东西,主要看他的 execute和enqueue方法
@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);
}
} finally {
client.dispatcher().finished(this);
}
}
}
由此可见execute确实是执行在调用它的线程里面的,看代码应该是通过getResponseWithInterceptorChain()来具体执行的,看到了似曾相识的interceptor,其实这里是运用了责任链设计模式的拦截器,这个稍后再说 execute方法暂时先告一段落,接下来看enqueue
@Override public void enqueue(Callback responseCallback) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
//看来这里才是真正执行的方法,继续跟踪,发现了一个dispather,并且还new了一个AsyncCall对象,传入了我们的匿名内部类接口实例
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
上面跟踪到了一个dispather,这个又是个什么鬼?字面理解是分发器,看来事情没有这么简单啊,继续跟进
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
//咦,这个不是线程池嘛
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
我们逮到了dispather的enqueue,发现他的call是丢给了线程池了,那么这个call,也就是AsyncCall是什么?先来看看它吧
/**
*注意这个类在RealCall类里面哦,是其内部类
*/
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;
}
//发现AsyncCall也有一个execute方法,和RealCall差不多
@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;
//这个是传进来的回调啦,它不是UI线程
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);
//这个也是传进来的回调啦,它也不是UI线程
responseCallback.onFailure(RealCall.this, e);
}
} finally {
client.dispatcher().finished(this);
}
}
}
原来它实现了NamedRunnable,那么这个NamedRunnable应该是实现了Runnable,然后我们这个execute没有在这里被调用,猜想应该是被父类重写的run给调用了,然后这个run应该是在线程池中的,验证下
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();
}
回到RealCall的enqueued来,是不是思路清晰多了。
首先,newCall(request)初始化request后生成了一个RealCall,紧接着RealCall的execute开始执行这个请求,如果异步,就是传入enqueue(callback),然后调用dispather.enqueue(new AsyncCall(callback)),这个AsyncCall呢他是RealCall内部类所以同样可以访问到newCall(request)初始化后的request,它持有callback回调同时又是个Runnable,并且它的run方法调用了他自己和外部类RecalCall名称相同功能相似的execute方法,然后这个AsyncCall在dispather里面是丢给线程池执行的,这样一来问题就通了。
@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));
}
说了这么久dispather?这个dispather到底是啥?别急,继续看
private int maxRequests = 64;
private int maxRequestsPerHost = 5;
...
public Dispatcher(ExecutorService executorService) {
this.executorService = executorService;
}
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,非核心线程int的最大值,但是外面maxRequest和 maxRequestsPerHost已经限制了它的并发线程数了,非核心线程60s超时时间,阻塞队列是SynchronousQueue,也就是不存储元素的队列,进了必出。到此问题已经基本解决。
下面说一下getResponseWithInterceptorChain()
//这个是真正发起请求的方法
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);
}
继续看chain.proceed,看之前顺便提下责任链设计模式。典型的责任链模式,是定义一个责任链节点对象抽象类,定义一个消息抽象类,每个节点对象必须实现抽象类的handleMessage(Object message)方法,然后对传进来的消息按实际情况处理,未处理完或者不能处理的交给下一个链节点对象,直到消息处理完毕。
责任链体现了典型的分层思想,分层的好处是显而易见的,复杂简单化,灵活和易于维护。比如TCP/IP协议就是经典的例子。
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.
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);
// 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");
}
if (response.body() == null) {
throw new IllegalStateException(
"interceptor " + interceptor + " returned a response with no body");
}
return response;
}
简单总结下上面代码,其实大概就是getResponseWithInterceptorChain()里面先实例化一条责任链,注册各种拦截器(链节点对象),然后通过chain.proceed获得下一个拦截器(节点)
// Call the next interceptor in the chain.
RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
writeTimeout);
Interceptor interceptor = interceptors.get(index);
每次调用chain对象proceed获得节点后,节点的intercept取出chain里面的request处理,然后用户在里面又调用procee,index+1,获得下一个拦截器,然后调用拦截器的拦截方法intercept,用户里面又取出chain里面的request处理,继续循环下去。
简要说下拦截器
- 应用拦截器(用户添加)
- 重定向等的拦截器
- 构造请求头的拦截器
- 缓存拦截器
- 连接拦截器
- 网络拦截器(用户添加)
- 数据传输拦截器
最后附上网络上的两个图总结
OkHttp流程
拦截器
最后
如果你看到了这里,觉得文章写得不错就给个赞呗?如果你觉得那里值得改进的,请给我留言。一定会认真查询,修正不足。谢谢。
希望读到这的您能转发分享和关注一下我,以后还会更新技术干货,谢谢您的支持!
转发+点赞+关注,第一时间获取最新知识点
Android架构师之路很漫长,一起共勉吧!
——————分割线——————
简书点赞可以有好几种赞,长按点赞按钮就会有选项,大家点赞的时候,麻烦点个超赞~
网友评论