1.OkHttp(OkHttp的版本implementation "com.squareup.okhttp3:okhttp:3.12.3")的常规用法,如下:
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("")
.build();
client.newCall(request)
.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException
{
}
});
1.上面的代码中,首先从点进去enqueue()方法点进去,enqueue()方法是Call接口类中的一个抽象方法,因而继续向上寻找,点击newCall(request)方法,点进去之后,代码如下:
/**
* 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.newRealCall(this,request,false)方法返回了一个实现Call接口的实例对象。我们接着往下走,点击newRealCall这个方法,代码如下:
static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
// Safely publish the Call instance to the EventListener.
//这句的大致意思是将Call的实例对象安全的发布到EventListener中
RealCall call = new RealCall(client, originalRequest, forWebSocket);
call.eventListener = client.eventListenerFactory().create(call);
return call;
}
从newRealCall()方法中参数request 是指请求报文,forWebSocket用于比较频繁的请求协议,并且服务器可以向客户端发消息,一般使用的场景股票,金融类的APP,需要秒级别的刷新频率。然后eventListener是一个监听器,他监听请求连接、请求报文等,另外由于RealCall实现了Call接口,而enqueue()方法又是接口Call里面的抽象方法,所以RealCall肯定也实现了enqueue()方法,其具体代码如下:
@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));
}
这段代码重点在最后一行client.dispatcher().enqueue(new AsyncCall(responseCallback)),先说client.dispacher()方法,此方法返回了一个dispatcher对象,Dispatcher是线程的的调度器,用于多线程管理,其中需要关注的两个关键变量1.maxRequest最大请求数2.maxRequestPerHost每个主机最大请求数,这两个变量可以配置配置方式setMaxRequest()和setMaxRequestsPerHost()进行配置。另外就是Dispatcher.enqueue()方法,其代码如下:
void enqueue(AsyncCall call) {
synchronized (this) {
readyAsyncCalls.add(call);
}
promoteAndExecute();
}
这个方法很简单就是将异步的call放进一个队列,然后执行promoteAndExecute()方法,我们去看一下promoteAndExecute()方法代码如下:
/**
*Promotes eligible calls from {@link #readyAsyncCalls} to {@link #runningAsyncCalls}
*and runs them on the executor service. Must not be called with synchronization
*because executing calls can call into user code.
*大致意思是把符合条件的call推举出来并执行,符合条件是指没有执行过的,没有超过最大请求数
*
* @return true if the dispatcher is currently running calls.
*/
private boolean promoteAndExecute() {
assert (!Thread.holdsLock(this));
List<AsyncCall> executableCalls = new ArrayList<>();
boolean isRunning;
synchronized (this) {
for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
AsyncCall asyncCall = i.next();
if (runningAsyncCalls.size() >= maxRequests) break; // Max capacity.
if (runningCallsForHost(asyncCall) >= maxRequestsPerHost) continue; // Host max capacity.
i.remove();
executableCalls.add(asyncCall);
runningAsyncCalls.add(asyncCall);
}
isRunning = runningCallsCount() > 0;
}
for (int i = 0, size = executableCalls.size(); i < size; i++) {
AsyncCall asyncCall = executableCalls.get(i);
asyncCall.executeOn(executorService());
}
return isRunning;
}
这方法主要是:
第一.将符合条件的Call挑选出来放入队列;
第二将这些符合条件放入推举队列中;
第三.第三步执行这些符合条件的队列;
在第三步执行call中,调用了AsynCall中的executeOn(),而AsyncCall是RealCall的内部类,并且实现了NamedRunnable接口,
/**
* 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) {
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);
eventListener.callFailed(RealCall.this, ioException);
responseCallback.onFailure(RealCall.this, ioException);
} finally {
if (!success) {
client.dispatcher().finished(this); // This call is no longer running!
}
}
}
这个方法的核心在executorService.excute(this)方法,这个方法的作用是切线程,this是指在AsyncCall中的run()方法,而在Run()在AsyncCall里面没有故而去父类NamedRunnable里面找,代码如下:
@Override
public final void run() {
String oldName = Thread.currentThread().getName();
Thread.currentThread().setName(name);
try {
execute();
} finally {
Thread.currentThread().setName(oldName);
}
}
这个方法的核心是execute()方法,而这个方法在NamedRunnable里面是抽象方法,因此从其实现的子类AysncCall中去找,其代码如下:
@Override
protected void execute() {
boolean signalledCallback = false;
timeout.enter();
try {
Response response = getResponseWithInterceptorChain();
signalledCallback = true;
responseCallback.onResponse(RealCall.this, response);
} catch (IOException e) {
e = timeoutExit(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);
}
}
}
这个方法主要获取getResponseWithInterceptorChain(),而此时是在子线程中,而getResponseWithInterceptorChain()这个方法主要涉及OKHTTP的拦截器,这个在下面一篇文章专门讲这个