RealCall 是哪里来的呢?故事的开始是从下面揭开的:
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});
这里,我们通过 okhttpclient 通过newCall 方法,返回了一个对象,然后,调用这个对象的enqueue方法,并且传了一个Callback 接口对象等待结果的回调。 然后,我们先看看这个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 */);
}
这个 newCall 是被重写了,我们看下是重写谁的方法
public interface Call extends Cloneable {
//省略代码
interface Factory {
Call newCall(Request request);
}
}
这个其实是Call接口中内置的工厂接口,也就是说,okhttpclient 实现了 Call中内置的工厂接口,重写了接口里的 newCall 方法
public class OkHttpClient implements Cloneable, Call.Factory, WebSocket.Factory {
它返回的是一个Call 类型的对象, 同时,这个对象是由RealCall 的newRealCall 方法返回的。我们看下这个RealCall 的实现
final class RealCall implements Call {
它也实现了Call 接口,那么这个Call 对象的 enqueue 方法呢?我们看下
public interface Call extends Cloneable {
void enqueue(Callback responseCallback);
也是Call 接口的方法,留待子类实现,然后通过接口被调用。
如此一来,目前知道的是:
newCall 方法 是 Call.Factory 接口的方法,okhttpclient 通过实现Call.Factory接口,把 RealCall 搞出来。
enqueue 方法是 Call 接口的方法,RealCall 通过实现Call 接口,重写了enqueue 方法。
我们看看RealCall 主要做了什么东西
public class RealCall {
//用来调用触发请求,它里面有个 dispatcher ,dispatcher 用来处理请求队列
final OkHttpClient client;
/**
* There is a cycle between the {@link Call} and {@link Transmitter} that makes this awkward.
* This is set after immediately after creating the call instance.
*/
//用来控制连接,监听连接,请求的状态等
private Transmitter transmitter;
/** The application's original request unadulterated by redirects or auth headers. */
//开发者传进来的原始请求体,里面有请求的地址url,端口port,入参 body等一堆信息
final Request originalRequest;
//标记是啥请求? 一般是false
final boolean forWebSocket;
// Guarded by this.
//标记当前请求RealCall的执行状态,如果该值为true, 那么再去执行请求的时候,就会抛异常
private boolean executed;
/**
这个构造方法私有化了,也就是说RealCall 不能直接new出来,所以,才有下面静态方法
*/
private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
this.client = client;
this.originalRequest = originalRequest;
this.forWebSocket = forWebSocket;
}
/**
这个方法接收了3个参数,分别是客户端,原始请求体,用来标记socket类型的变量,不过这个标记一般都是false的
这个RealCall被new出来之后,传给了Transmitter ,Transmitter new出来后,又放到了RealCall里,是不是蜜汁操作
*/
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.transmitter = new Transmitter(client, call);
return call;
}
@Override public Request request() {
return originalRequest;
}
/**
* 1、先判断call的执行状态,如果重复执行就抛个异常
* 2、初始化 transmitter 的设置,设置超时机制,就是请求之前要设置好超时时间,以及反馈请求开始事件
* 3、通过客户端持有的 dispatcher,调用它的执行方法,触发下一步操作
* 4、就返回请求结果了
* 最后必须执行的一步:结束请求这个请求的操作,不管请求的结果是怎样,包括在请求队列里移除
* @return
* @throws IOException
*/
@Override public Response execute() throws IOException {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
transmitter.timeoutEnter();
transmitter.callStart();
try {
client.dispatcher().executed(this);
return getResponseWithInterceptorChain();
} finally {
client.dispatcher().finished(this);
}
}
/**
* 这个跟上面的 execute 不同在于,这个是异步的,所以,你会发现,需要穿入一个 Callback,用来回调结果给开发者
* 1、先判断call的执行状态,如果重复执行就抛个异常
* 2、transmitter 反馈请求开始事件
* 3、通过客户端持有的 dispatcher,调用它的执行方法,触发下一步操作,Callback是放在 AsyncCall 里,再将AsyncCall传入 dispatcher
* @param responseCallback
*/
@Override public void enqueue(Callback responseCallback) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
transmitter.callStart();
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
/**
* 取消请求
*/
@Override public void cancel() {
transmitter.cancel();
}
/**
* 获取超时策略
* @return
*/
@Override public Timeout timeout() {
return transmitter.timeout();
}
/**
* 当前call的执行状态
* @return
*/
@Override public synchronized boolean isExecuted() {
return executed;
}
/**
* call的取消状态
* @return
*/
@Override public boolean isCanceled() {
return transmitter.isCanceled();
}
/**
* 这个就是复制的作用,将当前的call重新弄个拷贝出来,可以用来发多一次请求
* @return
*/
@SuppressWarnings("CloneDoesntCallSuperClone") // We are a final type & this saves clearing state.
@Override public RealCall clone() {
return RealCall.newRealCall(client, originalRequest, forWebSocket);
}
/**
* 这个就厉害了,这个 AsyncCall 继承的类,意味着它是一个线程,因为 NamedRunnable 实现了Runnable接口
* 所以大家把它当做是一个线程就好了,既然是线程,我们只要关注它的run方法就好了,但是,在 AsyncCall 里看不到run方法,翻看 NamedRunnable
* 就发现,原来 NamedRunnable 的run会调用 AsyncCall 的execute 方法
* 所以,我们要留意下 execute 做了什么
*
*/
final class AsyncCall extends NamedRunnable {
/**
* 就是请求的回调接口
*/
private final Callback responseCallback;
/**
* 用来存储当前请求的主机数,一般用于多线程的判断,因为它是原子性的,数据比较准确,线程安全
* volatile 关键字 加上 Unsafe 的帮助,使得它线程安全
*/
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;
}
/**
* 请求的服务器的地址
* @return
*/
String host() {
return originalRequest.url().host();
}
/**
* 请求体
* @return
*/
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.
*
* 机器翻译:尝试在executorService上将此异步调用加入队列。如果执行程序已通过将调用报告为失败而关闭,这将尝试进行清理。
*
* 在上面提到的 enqueue 方法中,这个方法最终就是会走到这里来,通过 ExecutorService线程池进行启动线程
* 当启动线程后,就是意味着 AsyncCall 的 execute 方法被调用了,因为刚说了继承自线程,execute 方法在run 里面
*
* 在执行线程后,同时会伴随一个捕捉线程池拒绝服务的异常,为啥呢?因为这个是防止线程不被执行时的操作,当线程别拒绝了,就会走
* 回调 onFailure 了,以及 transmitter 也做了一些列的连接相关的操作
*
* 最后一步,对执行结果进行判断,如果线程不成功,则客户端通过自身的 dispatcher 结束这个call的运行,请求队列里移除这个call
*
* @param executorService
*/
void executeOn(ExecutorService executorService) {
assert (!Thread.holdsLock(client.dispatcher()));
boolean success = false;
try {
executorService.execute(this);
success = true;
} catch (RejectedExecutionException e) {
InterruptedIOException ioException = new InterruptedIOException("executor rejected");
ioException.initCause(e);
transmitter.noMoreExchanges(ioException);
responseCallback.onFailure(RealCall.this, ioException);
} finally {
if (!success) {
client.dispatcher().finished(this); // This call is no longer running!
}
}
}
/**
* 线程启动的时候,走这里
* 1、这里也有个transmitter的超时设置,刚才在同步请求那里也有
* 2、启动拦截器链了
* 3、设置了标志位,处理回调二次调用的异常
* 4、不管怎样,最后一步,请求结束后都清除请求
*/
@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);
}
} catch (Throwable t) {
cancel();
if (!signalledCallback) {
IOException canceledException = new IOException("canceled due to " + t);
canceledException.addSuppressed(t);
responseCallback.onFailure(RealCall.this, canceledException);
}
throw t;
} finally {
client.dispatcher().finished(this);
}
}
}
/**
* Returns a string that describes this call. Doesn't include a full URL as that might contain
* sensitive information.
*/
String toLoggableString() {
return (isCanceled() ? "canceled " : "")
+ (forWebSocket ? "web socket" : "call")
+ " to " + redactedUrl();
}
String redactedUrl() {
return originalRequest.url().redact();
}
/**
* 这里是拦截器的配置相关
* 1、如果开发者另外配置了应用拦截器,就将这类拦截器放入集合中
* 2、依次添加 RetryAndFollowUpInterceptor ,BridgeInterceptor ,CacheInterceptor ,ConnectInterceptor 4个拦截器
* 3、如果不是 forWebSocket ,就要把开发者配置的网络拦截器也要放入集合中
* 4、添加 CallServerInterceptor 拦截器
* 5、构建一个拦截器链,拦截器链上有拦截器的信息,请求体,读、写、连接超时,transmitter 等东西。
* 6、拦截器链开始处理,返回结果就是 Response 了
* @return
* @throws IOException
*/
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List<Interceptor> interceptors = new ArrayList<>();
interceptors.addAll(client.interceptors());
interceptors.add(new RetryAndFollowUpInterceptor(client));
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, transmitter, null, 0,
originalRequest, this, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
boolean calledNoMoreExchanges = false;
try {
Response response = chain.proceed(originalRequest);
if (transmitter.isCanceled()) {
closeQuietly(response);
throw new IOException("Canceled");
}
return response;
} catch (IOException e) {
calledNoMoreExchanges = true;
throw transmitter.noMoreExchanges(e);
} finally {
if (!calledNoMoreExchanges) {
transmitter.noMoreExchanges(null);
}
}
}
}
我在代码里做了一些注释,方便认识。
但总的来说,RealCall主要做了以下:
1、接收开发者传进来的请求信息,这些请求信息包括请求的地址,提交的参数body,okp客户端等信息
2、它内置了一个线程的实现,所以,请求都是在线程里面处理的
3、里面分别有同步请求,异步请求两个逻辑处理,其中异步请求是通过 dispatcher 分配的
4、配置了拦截器,并且开始向拦截器提交请求体