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

来源:互联网 发布:中介管理系统源码 编辑:程序博客网 时间:2024/05/22 11:41

当通过自定义的接口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请求流程完成

2 0
原创粉丝点击