Okhttp 源码分析(1)----流程分析

分析版本为 3.0.5

一般app gradle中引用:

    compile 'com.squareup.okhttp3:okhttp:3.5.0'

下面根据使用来分析调用的流程,仅限调用的流程!

1.OkHttpClient

Call call = mOkHttpClient.newCall(request);
call.enqueue(new Callback());

通过OkHttpClient调用newCall方法,获取call对象,Call是个interface,实际实现类是Realcall类。

2.Realcall

这个类十分的关键,里面有同步execute请求,异步enqueue请求,同时里面还有个内部类AsyncCall,后面调用的时候再分析
直接看异步请求(同步请求类似,话说你们会用同步的请求吗?)

  @Override public void enqueue(Callback responseCallback) {
    //省略部分代码
    client.dispatcher().enqueue(new AsyncCall(responseCallback));
  }

注意,返回类型是void,那么我们的response跑哪里去了呢?先不着急,先看看Dispatcher是什么鬼。

3.Dispatcher

  private int maxRequests = 64;//最大请求个数
  private int maxRequestsPerHost = 5;//最大主机响应个数
  private Runnable idleCallback;
  private ExecutorService executorService;//线程池
  private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();//待定异步请求队列
  private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();//正在运行异步请求队列
  private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();//正在运行同步请求队列

继续第二步中的client.dispatcher().enqueue()代码:

  synchronized void enqueue(AsyncCall call) {
    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
      runningAsyncCalls.add(call);//满足条件加入队列中
      executorService().execute(call);//执行
    } else {
      readyAsyncCalls.add(call);//满足条件加入队列中
    }
  }

executorServicesh是一个线程池对象,构造方法为:

  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().execute(call);//执行

再次阅读这行代码,大家应该就会明白什么意思了吧。也即执行线程的run方法,call是AsyncCall 我们在步骤一中提到过,是Realcall的内部类,来看看其代码

4.AsyncCall

final class AsyncCall extends NamedRunnable {
//省略部分代码

    @Override protected void execute() {
      boolean signalledCallback = false;
      try {
        Response response = getResponseWithInterceptorChain();//重点1
        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);//重点2
      }
    }
  }

NamedRunnable继承自Runnable接口,run方法中调用execute方法,所以也即AsyncCall 实现自Runnable,run方法对应execute,步骤3中调用的execute实际调用的就是该类中的execute方法。
好累啊,绕来绕去还是Realcall中的类,但是我们的Dispatch却实现了其多线程的功能了,是不是很赞!

代码中,可以看到Response对象的返回了,也即调用:

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

这个方法,主要是为了加一些拦截器,拦截器的概念可以简单理解为:在Response之前和之后可以分别做一些自己的操作,比如最简单的打印log,完全可以用拦截器来实现,interceptors.addAll(client.interceptors())意思为添加我们自定义的拦截器,其他为一些系统定义的拦截器。最后调用RealInterceptorChain的proceed方法。

6.RealInterceptorChain

public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
      Connection connection) throws IOException {
    //省略部分代码
    RealInterceptorChain next = new RealInterceptorChain(
        interceptors, streamAllocation, httpCodec, connection, index + 1, request);
    Interceptor interceptor = interceptors.get(index);
    Response response = interceptor.intercept(next);
    //省略部分代码
    return response;
  }

创建一个RealInterceptorChain对象,获取一个Interceptor对象,调用intercept方法,怎么就返回了Response对象了呢?所以还是看看intercept是什么吧。

7.Interceptor

看看其实现类,retryAndFollowUpInterceptor(如果没有自己添加的拦截器,index=0时获取就是该拦截器)

拦截器都是实现自Interceptor,先看看其源码

public interface Interceptor {
  Response intercept(Chain chain) throws IOException;
  interface Chain {
    Request request();
    Response proceed(Request request) throws IOException;
    Connection connection();
  }
}

深入retryAndFollowUpInterceptor的源码的intercept方法你会发现,内部调用chain的proceed方法,原来是循环嵌套调用RealInterceptorChain的proceed方法,一个一个拦截器的intercept的方法调用后,最后调用到CallServerInterceptor的这个拦截器,并且,其intercept方法中实现了网络请求调用,终于找到了!!!

8.CallServerInterceptor

@Override public Response intercept(Chain chain) throws IOException {
    HttpCodec httpCodec = ((RealInterceptorChain) chain).httpStream();
    StreamAllocation streamAllocation = ((RealInterceptorChain) chain).streamAllocation();
    Request request = chain.request();

    long sentRequestMillis = System.currentTimeMillis();
    httpCodec.writeRequestHeaders(request);

    if (HttpMethod.permitsRequestBody(request.method()) && request.body() != null) {
      Sink requestBodyOut = httpCodec.createRequestBody(request, request.body().contentLength());
      BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut);
      request.body().writeTo(bufferedRequestBody);
      bufferedRequestBody.close();
    }

    httpCodec.finishRequest();

    Response response = httpCodec.readResponseHeaders()
        .request(request)
        .handshake(streamAllocation.connection().handshake())
        .sentRequestAtMillis(sentRequestMillis)
        .receivedResponseAtMillis(System.currentTimeMillis())
        .build();

    int code = response.code();
    if (forWebSocket && code == 101) {
      // Connection is upgrading, but we need to ensure interceptors see a non-null response body.
      response = response.newBuilder()
          .body(Util.EMPTY_RESPONSE)
          .build();
    } else {
      response = response.newBuilder()
          .body(httpCodec.openResponseBody(response))
          .build();
    }

    if ("close".equalsIgnoreCase(response.request().header("Connection"))
        || "close".equalsIgnoreCase(response.header("Connection"))) {
      streamAllocation.noNewStreams();
    }

    if ((code == 204 || code == 205) && response.body().contentLength() > 0) {
      throw new ProtocolException(
          "HTTP " + code + " had non-zero Content-Length: " + response.body().contentLength());
    }

    return response;
  }

这个方法中,实现最后的网络请求,原来拦截器的功能这么强大呢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值