OkHttp 执行流程与为什么Callback在子线程中执行

当通过自定义的接口Server返回一个Call对象后,要执行请求就要调用Call的

enQueue方法或者execute方法,由于execute方法是同步方法,所以略过。Call是一个接口,

真正执行该方法的是Call的实现类(仅此一个实现类)RealCall的enqueue方法如下


  @Override public void enqueue(Callback responseCallback) {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace();
    client.dispatcher().enqueue(new AsyncCall(responseCallback));
  }


在这里,我们可以看到最终Callback被装饰为一个AsyncCall的类,而这个类其实是Runable的
子类,而client.dispatcher 在我看来是一个线程池。然后这个线程池将我们的回调加入了队列,

然后是Dispatcher的enqueue方法的实现


  synchronized void enqueue(AsyncCall call) {
    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
      runningAsyncCalls.add(call);
      executorService().execute(call);
    } else {
      readyAsyncCalls.add(call);
    }
  }

runningAsyncCalls和readyAsyncCalls是Deque类型的集合,而这个Deque继承与Queue,所以
这是两个队列,从代码可以看出,这个请求一个加入了正在运行的队列,一个加入了准备队列,
准备,加入运行队列之后,接着执行了 executorService().execute(call);


  public synchronized ExecutorService executorService() {
    if (executorService == null) {
      executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
          new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
    }
    return executorService;
  }

而executorService()方法返回了一个ExecutorService对象,该对象实现了Executor接口,而该
接口中,只有一个方法execute(),该方法官方文档给出的实现为


 class SerialExecutor implements Executor {
   final Queue<Runnable> tasks = new ArrayDeque<Runnable>();
   final Executor executor;
   Runnable active;

   SerialExecutor(Executor executor) {
     this.executor = executor;
   }

   public synchronized void execute(final Runnable r) {
     tasks.offer(new Runnable() {
       public void run() {
         try {
           r.run();
         } finally {
           scheduleNext();
         }
       }
     });
     if (active == null) {
       scheduleNext();
     }
   }

   protected synchronized void scheduleNext() {
     if ((active = tasks.poll()) != null) {
       executor.execute(active);
     }
   }
 }

从execute方法中我们可以看出,为什么callback在子线程调用了,那么接下来就是执行的最后一步,在run里进行了什么操作


来看下AsyncCall的构造方法和execute方法

    AsyncCall(Callback responseCallback) {
      super("OkHttp %s", redactedUrl());
      this.responseCallback = responseCallback;
    }

    @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 {
          responseCallback.onFailure(RealCall.this, e);
        }
      } finally {
        client.dispatcher().finished(this);
      }
    }

自这里调用了callback的onFailure和onResponse,那么这里似乎和上边的 SerialExecutor 中的 r.run() 并没有什么关系,那么让我们来看下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 {
      execute();
    } finally {
      Thread.currentThread().setName(oldName);
    }
  }

  protected abstract void execute();
}

这里可以看到NamedRunnable实现了Runnable并重写的run方法并在其中调用了execute()方法。到这里OkHttp请求流程完成

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值