okHttp基本流程

基本用法

同步:

OkHttpClient client = new OkHttpClient.Builder().build();
Request request = new Request.Builder().url("http://www.csdn.net").build();
try {
    client.newCall(request).execute();
} catch (IOException e) {
    e.printStackTrace();
}

异步:

OkHttpClient client = new OkHttpClient.Builder().dispatcher(dispatcher).build();
Request request = new Request.Builder().url("http://www.csdn.net").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 {
    }
});

同步流程分析

execute执行的的是RealCall的execute方法,如下

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

关键方法是getResponseWithInterceptorChain

Response getResponseWithInterceptorChain() throws IOException {
  // Build a full stack of interceptors.
  List<Interceptor> interceptors = new ArrayList<>();
  interceptors.addAll(client.interceptors());
  interceptors.add(retryAndFollowUpInterceptor);
  interceptors.add(new BridgeInterceptor(client.cookieJar()));
  interceptors.add(new CacheInterceptor(client.internalCache()));
  interceptors.add(new ConnectInterceptor(client));
  if (!forWebSocket) {
    interceptors.addAll(client.networkInterceptors());
  }
  interceptors.add(new CallServerInterceptor(forWebSocket));

  Interceptor.Chain chain = new RealInterceptorChain(
      interceptors, null, null, null, 0, originalRequest);
  return chain.proceed(originalRequest);
}

这里是责任链模式,生成了一个调用链,这里先看一下责任链是怎么进行调用的,再看每个Interceptor的作用

责任链

RealInterceptorChain的processed方法如下(省略非关键代码)

public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
  ...
  // Call the next interceptor in the chain.
  RealInterceptorChain next = new RealInterceptorChain(
      interceptors, streamAllocation, httpCodec, connection, index + 1, request);
  Interceptor interceptor = interceptors.get(index);
  Response response = interceptor.intercept(next);
  ...
  return response;
}

这里先为index + 1以后的Interceptor生成一个新的责任链,然后调用第index个Interceptor,Interceptor.intercept方法一般如下

@Override 
public Response intercept(Chain chain) throws IOException {
  // 做前置处理  
  Response response = chain.proceed(requestBuilder.build());
  // 做后置处理
  return response;
}

这里的入参chain就是刚刚生成的index + 1的责任链RealInterceptorChain,这里Interceptor调用proceed开启责任链的下一步,在调用前后可以做前/后置处理。举个例子,如果责任链上有ABC三个节点,那么实际的调用顺序是:
A前置 -> B前置 -> C -> B后置 -> A后置。

okHttp各Interceptor功能简述

在getResponseWithInterceptorChain中有一下一个调用链

各个Interceptor的实现后续再详细分析

清理工作

RealCall.execute方法的最后会调用dispatcher的finish方法

/** 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();
  }
}

这里做的清理工作比较简单,就是把RealCall从dispatcher的runningSyncCalls中remove掉,如果调用者自定义的idleCallback,会调用它。promoteCalls里处理的是异步调用,这里因为入参promoteCalls是false,所以不会调用到

异步调用

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

Dispatcher.enqueue

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

如果已经正在执行的异步任务达到上限,就加入到异步准备队列,否则放到线程池中执行。执行的话,会调用到AsyncCall.execute,这里跟同步任务几乎一样,不再分析。如果是放到准备队列里的话,在一个异步任务执行完毕进行清理的时候,会调用finish,这里传入的promoteCalls是true

/** Used by {@code AsyncCall#run} to signal completion. */
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) {
    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();
  }
}

private void promoteCalls() {
  if (runningAsyncCalls.size() >= maxRequests) return; // Already running max capacity.
  if (readyAsyncCalls.isEmpty()) return; // No ready calls to promote.

  for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
    AsyncCall call = i.next();

    if (runningCallsForHost(call) < maxRequestsPerHost) {
      i.remove();
      runningAsyncCalls.add(call);
      executorService().execute(call);
    }

    if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity.
  }
}

因此,会调用到promoteCalls()方法,尝试进行准备队列里异步任务的执行。

基本流程就到此结束了,详细分析见后续

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值