异步get
private void getData() {
String url = "https://wwww.baidu.com";
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.build();
final Request request = new Request.Builder()
.url(url)
.get()
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d(TAG, "onFailure: ");
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d(TAG, "onResponse: " + response.body().string());
}
});
}
call.enqueue():
@Override public void enqueue(Callback responseCallback) {
synchronized (this) {
//call是否被执行过
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
client.dispatcher()
//在public class OkHttpClient类下
public Dispatcher dispatcher() {
return dispatcher; //dispatcher在OkHttpClient的Builder()的时候已经初始化
}
client.dispatcher().enqueue
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
enqueue()总结:
1.判断当前call是否执行过;
2.把传过来等call封装成一个AsyncCall对象,AsyncCall其实就是一个runnable
3.client.dispatcher().enqueue()进行异步请求:当正在请求当runnable个数小于64并且当前网络请求当host小于5个请求当时候,这时会把runnable放到请求异步队列当中,然后通过线程池去执行call的请求。如果不是,会把runnable添加到等待就绪当异步请求队列当中。
线程池执行call请求
@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);
}
}
判断请求重定向(retryAndFollowUpInterceptor)是否被取消,如果被取消,回调onFailure;如果没有被取消,回调onResponse。最后调用client.dispatcher().finished(this)
client.dispatcher().finished(this)
void finished(AsyncCall call) {
finished(runningAsyncCalls, call, true);
}
private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
int runningCallsCount;
Runnable idleCallback;
synchronized (this) {
//把当前的call从运行的runnable里移除
if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
//调整正在异步请求的队列,把待请求的call加入进去
if (promoteCalls) promoteCalls();
//重新计算正在请求的线程数
runningCallsCount = runningCallsCount();
idleCallback = this.idleCallback;
}
if (runningCallsCount == 0 && idleCallback != null) {
idleCallback.run();
}
}
okhttp的任务调度
okhttp如何实现同步和异步请求?
发送的同步/异步请求都会在dispatcher中管理其状态
dispatcher的作用
维护请求的状态,维护一个线程池,用于执行请求。
public final class Dispatcher {
···
//维护了一个异步高效的线程池来执行网络操作
private @Nullable ExecutorService executorService;
//就绪状态的异步请求状态
private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();
//正在执行的的异步请求,包含:已经取消,但是没有执行完的请求
private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();
private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();
}
网友评论