OkHttp3学习(二):发送一个请求

OkHttp3学习(一):基本使用中记录了怎么使用OkHttp设置一个指定的请求,我们请求的参数有了,之后我们就是发起请求了。那么OkHttp3又是怎么发起的这次请求呢?

先看下之前的一个GET请求

 OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .get()
                .url(PATH)
                .build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()) {
                    String string = response.body().string();
                    Log.i(TAG, "onResponse: "+string);
                }
            }
        });

在这次请求中我们设置好Request请求的相关参数之后,我们就调用了。client.newCall(request)。从字面意思猜测这个newCall就是在创建一次新的请求。

Call

Call是一个接口,源码是这样的。(OkHttpClient实现了Call.Factory接口)

public interface Call extends Cloneable {

  Request request(); //返回发起这个Call的原始Request

  Response execute() throws IOException; //执行请求

  void enqueue(Callback responseCallback); //在以后的某个时间点执行

  void cancel(); //取消请求 如果请求已经成功了就不能取消了

  boolean isExecuted(); //是否正在执行

  boolean isCanceled(); //是否取消了

  Call clone();

  interface Factory {
    Call newCall(Request request);
  }
}

newCall

来看下client.newCall(request)都干了些什么。

/**
   * Prepares the {@code request} to be executed at some point in the future.
   */
  @Override public Call newCall(Request request) {
    return new RealCall(this, request, false /* for web socket */);
  }

通过源码看到。在这里我们是创建了一个RealCall的实例。之后我们又调用了RealCallenqueue()。来看下。

  @Override public Response execute() throws IOException {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace();
    try {
      client.dispatcher().executed(this);
      Response result = getResponseWithInterceptorChain();
      if (result == null) throw new IOException("Canceled");
      return result;
    } finally {
      client.dispatcher().finished(this);
    }
  }
 @Override public void enqueue(Callback responseCallback) {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace();
    client.dispatcher().enqueue(new AsyncCall(responseCallback));
  }

进入方法,先判断是否执行了。之后调用了captureCallStackTrace(),之后我们就看到了。这次请求是通过OkHttpClientDispatcher调度器执行的。(client.dispatcher()返回OkHttp的成员变量Dispatcher)。我们看到enqueue()executed()都是调用了Dispatcher的方法。

 /** Used by {@code Call#execute} to signal it is in-flight. */
  synchronized void executed(RealCall call) {
    runningSyncCalls.add(call);
  }

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

在这部分代码中。runningAsyncCalls异步请求的双端队列。 runningSyncCalls同步请求的双端队列。
尽管RealCallAsyncCall都叫做Call。但是还是有点区别的。AsyncCallRunnable的间接子类并没有实现Call接口或者集成Call,而RealCall则是一个Call的子类。他们有着本质上的区别。

/** Running asynchronous calls. Includes canceled calls that haven't finished yet. */
  private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();

  /** Running synchronous calls. Includes canceled calls that haven't finished yet. */
  private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();

AcyncCall

在上面的代码中我们可以看到enqueue在执行的时候是同过executorService()来执行的。该方法会返回一个ExecutorService,同事也初始化了Dispatcher中的executorService 变量。

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

Dispatcher通过这个execurorService来管理着所有异步请求(AcyncCall)。
同步请求是通过调用RealCallexecute()方法执行的,异步请求是通过AsyncCallexecute来执行的。
不过AsyncCallexecute()是在父类NamedRunnablerun()方法中调用的,也就是由线程池来管理着。
分析AsyncCallRealCallexecute()方法我们会看到,都会执行

   finally {
        client.dispatcher().finished(this);
      }

都执行了Dispatcherfinished()函数,来看下:

/** Used by {@code AsyncCall#run} to signal completion. */
  void finished(AsyncCall call) {
    finished(runningAsyncCalls, call, true);
  }

  /** Used by {@code Call#execute} to signal completion. */
  void finished(RealCall call) {
    finished(runningSyncCalls, call, false);
  }

  private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
    int runningCallsCount;
    Runnable idleCallback;
    synchronized (this) {
      if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
      if (promoteCalls) promoteCalls();
      runningCallsCount = runningCallsCount();
      idleCallback = this.idleCallback;
    }

    if (runningCallsCount == 0 && idleCallback != null) {
      idleCallback.run();
    }
  }

从双端队列中取出call,如果是AsyncCall就执行promoteCalls()

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值