根据最简单的使用流程来看请求流程,先看异步返回
1. 异步返回最简单流程
1. 简单使用流程
val okHttpClient = OkHttpClient()
val request = Request.Builder()
.url(MyUrl.BASE_URL + MyUrl.JOKE_URL)
.build()
val newCall = okHttpClient.newCall(request)
newCall.enqueue(object :Callback{
override fun onFailure(call: Call, e: IOException) {
}
override fun onResponse(call: Call, response: Response) {
}
})
可以看出前几行是初试化初始数据,这里只传入了一个url,所以流程从newCall()
开始
2. okHttpClient.newCall()
//这里是OKHttpClient
@Override public Call newCall(Request request) {
// 这里调用了RealCall中的newRealCall来创建一个真实请求网络的Call,
// 请求参数分别为OKHttpClient,传入自定义的Request,
// webSocket(默认为false,这里包含了服务器的行为,一般不用,一些使用场景则需自己深究)
return RealCall.newRealCall(this, request, false /* for web socket */);
}
接下来看RealCall.newRealCall(this, request, false);
3. RealCall.newRealCall(this, request, false);
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;
}
可以看出newCall的实际是创建了一个RealCall实例,并且还创建了一个Transmitter实例,用于管理请求和响应之间的数据流传输,可以看出请求整个过程的生命监听管理。它负责处理请求的发送、响应的接收以及与底层网络交互的相关逻辑。
接下来看enqueue()
4. RealCall.enqueue(responseCallback)
@Override public void enqueue(Callback responseCallback) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
// 这里是进行状态传送,里面有个接口实例进行通知数据
transmitter.callStart();
// 这里使用的Dispatcher中的enqueue()
// 并且创建了一个新的AsyncCall
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
5. Dispatcher.enqueue(call)
void enqueue(AsyncCall call) {
synchronized (this) {
readyAsyncCalls.add(call);
// Mutate the AsyncCall so that it shares the AtomicInteger of an existing running call to
// the same host.
// 默认false
if (!call.get().forWebSocket) {
// 从准备好了的和正在运行的查找和新创建的Call是否连接同一个host,
// 是同一个则公用同一并请求数
// 这有助于控制对特定主机的并发请求数
AsyncCall existingCall = findExistingCallWithHost(call.host());
if (existingCall != null) call.reuseCallsPerHostFrom(existingCall);
}
}
promoteAndExecute();
}
6. AsyncCall.findExistingCallWithHost(host)
@Nullable private AsyncCall findExistingCallWithHost(String host) {
// 可以看出从正在运行的Call和准备好的Call查找以及创建和新创建相同的Call,根据host是否相同
for (AsyncCall existingCall : runningAsyncCalls) {
if (existingCall.host().equals(host)) return existingCall;
}
for (AsyncCall existingCall : readyAsyncCalls) {
if (existingCall.host().equals(host)) return existingCall;
}
return null;
}
7. Dispater.promoteAndExecute()
private boolean promoteAndExecute() {
assert (!Thread.holdsLock(this));
// 可执行的Call列表,后面也会将runningAsyncCalls装配进executableCalls
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 (asyncCall.callsPerHost().get() >= maxRequestsPerHost) continue; // Host max capacity.
i.remove();
// 连接特定主机数加一
asyncCall.callsPerHost().incrementAndGet();
// 添加可以运行的Call,并且正在运行的Call连接该主机数不超过maxRequests
// 当前连接同一主机不超过maxRequestsPerHost,
executableCalls.add(asyncCall);
runningAsyncCalls.add(asyncCall);
}
isRunning = runningCallsCount() > 0;
}
for (int i = 0, size = executableCalls.size(); i < size; i++) {
AsyncCall asyncCall = executableCalls.get(i);
//执行Call
asyncCall.executeOn(executorService());
}
return isRunning;
}
8. RealCall.executeOn(executorService)
void executeOn(ExecutorService executorService) {
assert (!Thread.holdsLock(client.dispatcher()));
boolean success = false;
try {
// 这里使用线程池,实际后台线程做工作的代码,this代表调用的是自己的execute
// 自己的execute在父类NamedRunnable中实现,父类继承Runnable,说明实际工作在run中
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!
}
}
}
9. NamedRunnable.run()
//NamedRunnable方法调用executeOn
@Override public final void run() {
String oldName = Thread.currentThread().getName();
Thread.currentThread().setName(name);
try {
// 这里可以看出该线程中调用了本类的这个方法,但这个方法是被abstract修饰
// 所以在子类实现,上面可以看出这一最简单实现方法且使用HTTP1版本子类为AsyncCall
execute();
} finally {
Thread.currentThread().setName(oldName);
}
}
10. AsycCall.execute()
@Override protected void execute() {
boolean signalledCallback = false;
transmitter.timeoutEnter();
try {
// 这里请求网络并返回数据getResponseWithInterceptorChain这个里面就是OKHttp最重要的几个拦截器,组成链并执行返回Response过程,这里没有深究
Response response = getResponseWithInterceptorChain();
signalledCallback = true;
// 通过我们自定义的CallBack实例,返回数据,
// 可以看出这里并没有返回到主线程中,所以不能直接修改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 {
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);
}
}
10. 异步总结
- OKHttpClient首先newCall会创建一个出来RealCall,用于表示和执行一个实际的 HTTP 请求。它是 Call 接口的实现类之一,负责管理和执行网络请求。
- 然后调用RealCall的enqueue进行异步请求,异步管理在Dispatcher中,它决定了 OkHttp 在一个时刻可以同时执行多少个请求以及如何处理这些请求的调度逻辑。
- 异步调用会执行AsyncCall的execute来在后台线程中去进行网络请求,在这其中会从线程池中获取一个线程来执行,执行结果返回还是在该线程中并未在主线程中。
2. 同步调用
1. 使用
// 由于Android请求网络不允许在主线程中
thread {
val execute = newCall.execute()
}
2. RealCall.execute()
@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);
// 这里直接获取结果Response返回
return getResponseWithInterceptorChain();
} finally {
client.dispatcher().finished(this);
}
}
3. 同步总结
在同步调用没有涉及线程切换,需要自己创建线程,前置步骤跟异步一样,由于没有切换线程,这里直接返回,并不是使用CallBack将值传回去。
总结
这里没有介绍getResponseWithInterceptorChain()
这个方法是OKHttp请求返回结果这一系列处理的核心方法,其中包含拦截器,篇幅问题和个人研究没详细,但必须了解。