在 OkHttp 中,分发器(Dispatcher)是负责调度和执行网络请求的组件。它管理着并发的请求数量以及请求的优先级,确保合理地使用底层的连接池和线程池,从而提高网络请求的效率和性能。
默认情况下,OkHttp 使用一个单例的分发器,它可以处理同时进行的最大请求数为 64。也可以通过自定义分发器来修改这些默认设置,以满足特定的需求。
以异步请求为例:
package okhttp3;
final class RealCall implements Call {
// ...
@Override public void enqueue(Callback responseCallback) {
// ...
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
// ...
}
执行了 Call.enqueue() 之后,调用到 Dispatcher.enqueue():
package okhttp3;
public final class Dispatcher {
private int maxRequests = 64; // 最大请求数量
private int maxRequestsPerHost = 5; // 同 Host 下最大请求数量
private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>(); // 异步准备队列
private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>(); // 异步执行队列
private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>(); // 同步执行队列
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call); // 线程池执行
} else {
readyAsyncCalls.add(call);
}
}
// ...
}
可以看到,Dispatcher 定义了三个对列,存放各个状态的任务,方便对各个状态的任务进行管理。调用了 Dispatcher.enqueue() 后会根据当前请求数量来控制任务是否执行,若当前请求数量过多,则先存储在异步等待队列当中。
那存储在等待队列啥时候才能宠幸这里面的任务呢?先来看操作准备队列的方法 Dispatcher.promoteCalls():
package okhttp3;
public final class Dispatcher {
// ...
private void promoteCalls() {
if (runningAsyncCalls.size() >= maxRequests) return; // 是否达到最大请求次数
if (readyAsyncCalls.isEmpty()) return; // 判断准备队列是否为空
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; // 是否达到最大请求次数
}
}
// ...
}
这个方法就是查询准备队列是否还有未执行的任务,若有则在线程池中执行
那在异步请求中这个方法什么时候会执行呢?
package okhttp3;
final class RealCall implements Call {
final class AsyncCall extends NamedRunnable {
// ...
@Override protected void execute() {
try {
// ...异步请求
} catch (IOException e) {
// ...异常处理
} finally {
client.dispatcher().finished(this); // 调用
}
// ...
}
}
// Dispatcher
void finished(AsyncCall call) {
finished(runningAsyncCalls, call, true);
}
private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
if (promoteCalls) promoteCalls(); // 调用了 promoteCalls()
}
在异步请求后调用了 finished(),最终会去轮询准备队列查看是否还有未执行的任务。这就是异步请求的完整流程。
同步比较简单,直接往同步请求队列加任务,就不展开了文章来源:https://www.toymoban.com/news/detail-521345.html
总结:OkHttp 的分发器在网络请求过程中起着非常重要的作用,它有效地管理并发请求、优化请求的顺序和执行,以及管理连接池和线程池,从而提供高效、可靠的网络请求功能。文章来源地址https://www.toymoban.com/news/detail-521345.html
到了这里,关于Android Okhttp3 分发器源码解析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!