okhttp的源码简单追踪

参考: 

https://blog.piasy.com/2016/07/11/Understand-OkHttp/

https://www.jianshu.com/p/82f74db14a18

1.基本调用方法

OkhttpClient client = new OkhttpClient();
Request request = new Request.Builder().url(url).build();
Response response = client.newCall(request).execute();

2.call:代表一个 request/response 对,定义了 execute enqueue cancel 等操作;一个call只能执行一次

public interface Call {
  Request request();

  Response execute() throws IOException;

  void enqueue(Callback responseCallback);

  void cancel();

  boolean isExecuted();

  boolean isCanceled();

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

3.client.newCall(request)

  @Override public Call newCall(Request request) {
    return new RealCall(this, request);
  }

4.realCall.execute():真正执行的是 getResponseWithInterceptorChain()

  //realcall 的 execute() 方法
  @Override public Response execute() throws IOException {

    //一个call只能执行一次
    //如果想要一个完全一样的 call,可以利用 call.clone 方法进行克隆获取
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }

    try {
      //dispatcher.executed(realcall)只是把 realcall 加入一个双向队列(deque)中等待执行
      client.dispatcher().executed(this);

      //真正执行网络请求的地方
      Response result = getResponseWithInterceptorChain(false);

      if (result == null) throw new IOException("Canceled");
      return result;
    } finally {

      //把 realcall 从双向队列(deque)中移除
      client.dispatcher().finished(this);
    }
  }

5.getResponseWithInterceptorChain():添加拦截器

  private 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 (!retryAndFollowUpInterceptor.isForWebSocket()) {
      interceptors.addAll(client.networkInterceptors());
    }
    interceptors.add(new CallServerInterceptor(
        retryAndFollowUpInterceptor.isForWebSocket()));

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


  //RealInterceptorChain:按照 index 从 interceptors 中获取拦截器
public final class RealInterceptorChain implements Interceptor.Chain {
  private final List<Interceptor> interceptors;
  private final int index;

  ...

  public Response proceed(Request request, StreamAllocation streamAllocation, HttpStream httpStream,
      Connection connection) throws IOException {
    ...

    // 获取拦截器链中的下一个chain
    RealInterceptorChain next = new RealInterceptorChain(
        interceptors, streamAllocation, httpStream, connection, index + 1, request);
    
    //获取当前chain对应的拦截器
    Interceptor interceptor = interceptors.get(index);
    
    //让当前的拦截器执行动作,并把下一个chain传递给拦截器,以逐次执行拦截器的功能
    Response response = interceptor.intercept(next);

    ...
  }
  ...
}

//拦截器的基本逻辑
@Override public Response intercept(Chain chain) throws IOException {
    Request request = chain.request();
    //1 Request阶段,该拦截器在Request阶段负责做的事情

    //2 调用RealInterceptorChain.proceed(),其实是在递归调用下一个拦截器的intercept()方法
    response = ((RealInterceptorChain) chain).proceed(request, streamAllocation, null, null);

    //3 Response阶段,完成了该拦截器在Response阶段负责做的事情,然后返回到上一层的拦截器。
    return response;   
}

6.Interceptor

1)Interceptor 与 chain: Interceptor 是 OkHttp 最核心的一个东西,它不仅仅负责拦截请求进行一些额外的处理(例如 cookie),它还把实际的网络请求、缓存、透明压缩等功能都统一了起来,每一个功能都只是一个 Interceptor,它们再连接成一个 Interceptor.Chain,环环相扣,最终圆满完成一次网络请求。

2)拦截器依次是

interceptors:调用者添加的拦截器;

RetryAndFollowUpInterceptor:顾名思义,负责失败重试和重定向;

BridgeInterceptor:桥接拦截器,负责把用户的request转换为发送给服务器的request,把服务器返回的response转换为用户需要的response;

CacheInterceptor:缓存拦截器

ConnectInterceptor:负责与服务器建立连接(Opens a connection to the target server);

networkInterceptors:也是调用者添加的网络拦截器;

CallServerInterceptor:负责向服务器 发送请求、读取响应数据

3)位置决定了功能,最后一个 Interceptor 一定是负责和服务器实际通讯的,重定向、缓存等功能一定是在实际通讯之前的。

 

 

7.ConnectInterceptor:根据源码可以看出,ConnectInterceptor 的功能是实际上获取 connection,而不是典型的拦截功能;

用责任链来描述interceptor更准确,ConnectInterceptor的责任就是获取真正的connection,使责任链后面的interceptor可以使用connection

public final class ConnectInterceptor implements Interceptor {
  public final OkHttpClient client;

  public ConnectInterceptor(OkHttpClient client) {
    this.client = client;
  }

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

    // We need the network to satisfy this request. Possibly for validating a conditional GET.
    boolean doExtensiveHealthChecks = !request.method().equals("GET");
    HttpStream httpStream = streamAllocation.newStream(client, doExtensiveHealthChecks);
    RealConnection connection = streamAllocation.connection();

    return realChain.proceed(request, streamAllocation, httpStream, connection);
  }
}

8.CallServerInterceptor:主要动作如下

1)向服务器发送 request header;
2)如果有 request body,就向服务器发送;
3)读取 response header,先构造一个 Response 对象;
4)如果有 response body,就在 3 的基础上加上 body 构造一个新的 Response 对象;

因此,httpStream.openResponseBody 是真正获取response数据的地方

5)httpStream 实际上是通过okio读取response数据的;okio又是封装了socket

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

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

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

    httpStream.finishRequest();

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

    if (!forWebSocket || response.code() != 101) {
      response = response.newBuilder()
          .body(httpStream.openResponseBody(response))
          .build();
    }

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

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

    return response;
  }

8.完整流程

 

9.同步请求与异步请求

    //同步请求 realCall.execute
    @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);
      }
    }

    //异步请求 realCall.enqueue(callback)
    @Override public void enqueue(Callback responseCallback) {
      synchronized (this) {
        if (executed) throw new IllegalStateException("Already Executed");
        executed = true;
      }
      client.dispatcher().enqueue(new AsyncCall(responseCallback));
    }
    //其中 enqueue(asyncCall)如下
    synchronized void enqueue(AsyncCall call) {
      if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
        runningAsyncCalls.add(call);
        executorService().execute(call);
      } else {
        readyAsyncCalls.add(call);
      }
  }

 

10.AsyncCall源码

可以看出,异步的的call实际上也是通过类似的 execute 方法来执行的,最终网络访问还是借助 getResponseWithInterceptorChain 实现的

  final class AsyncCall extends NamedRunnable {
    private final Callback responseCallback;

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

    String host() {
      return originalRequest.url().host();
    }

    Request request() {
      return originalRequest;
    }

    RealCall get() {
      return RealCall.this;
    }

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

11.Dispatcher:是一个任务调度器,它内部维护了三个双端队列

readyAsyncCalls:准备运行的异步请求
runningAsyncCalls:正在运行的异步请求
runningSyncCalls:正在运行的同步请求
1)同步请求就直接把请求添加到正在运行的同步请求队列runningSyncCalls中,
2)异步请求会做个判断,如果正在运行的异步请求不超过maxRequests(默认64),而且同一个host下的异步请求不得超过maxRequestsPerHost(默认5个人)个,则将请求添加到正在运行的同步请求队列中runningAsyncCalls,并开始执行请求,否则就添加到readyAsyncCalls继续等待。

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值