okhttp enqueue流程

1,277 阅读2分钟

 老样子看用法

 OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
       
            okHttpClient.newCall(new Request.Builder().build()).enqueue(new Callback() {
               @Override
               public void onFailure(Call call, IOException e) {
                   new Handler().post(new Runnable{                    showIO();
               }

               @Override
               public void onResponse(Call call, Response response) throws IOException {
new Handler().post(new Runnable{
                    showIO();
                        })
               }
           });

看下enqueue

 @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));
  }

接下来看dispathcher的enqueue方法

void enqueue(AsyncCall call) {
    synchronized (this) {
先把call加入准备异步队列
      readyAsyncCalls.add(call);

      // Mutate the AsyncCall so that it shares the AtomicInteger of an existing running call to
      // the same host.
      if (!call.get().forWebSocket) {
//复用之前的call
        AsyncCall existingCall = findExistingCallWithHost(call.host());
        if (existingCall != null) call.reuseCallsPerHostFrom(existingCall);
      }
    }
继续进行
    promoteAndExecute();
  }

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.
最大同时运行数请求为64个。超过就退出循环
        if (asyncCall.callsPerHost().get() >= maxRequestsPerHost) continue; // Host max capacity.
每个服务器最大运行请求数位为5 个。超过就结束接下来操作
        i.remove();
        asyncCall.callsPerHost().incrementAndGet();
        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;
  }

接下来看 asyncCall.executeOn(executorService());每个异步请求被封装成asyncCall

 final class AsyncCall extends NamedRunnable {

}
public abstract class NamedRunnable implements Runnable {
  protected final String name;

  public NamedRunnable(String format, Object... args) {
    this.name = Util.format(format, args);
  }

  @Override public final void run() {
    String oldName = Thread.currentThread().getName();
    Thread.currentThread().setName(name);
    try {
run方法中执行execute,
      execute();
    } finally {
      Thread.currentThread().setName(oldName);
    }
  }

  protected abstract void execute();
}



void executeOn(ExecutorService executorService) {
      assert (!Thread.holdsLock(client.dispatcher()));
      boolean success = false;
      try {
        executorService.execute(this);
此处会在线程池中执行AsyncCall 的run方法,即执行 AsyncCall 的execute方法        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!
        }
      }
    }

@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);
      }
    }
  }

此时我们可以发现enqueue方法是可以直接在主线程中执行的,因为异步asyncCall会在线程池的子线程中执行。回调也是在子线程中,所以通常我们enqueue的回调中利用handler切换线程