博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
OkHttp发起请求源码阅读(一)
阅读量:6275 次
发布时间:2019-06-22

本文共 6448 字,大约阅读时间需要 21 分钟。

1.基本使用

OkHttpClient okHttpClient = new OkHttpClient();    Request request = new Request.Builder()            .url("https://www.baidu.com/")            .build();    Call call = okHttpClient.newCall(request);    call.enqueue(new Callback() {        @Override        public void onFailure(Call call, IOException e) {        }        @Override        public void onResponse(Call call, Response response) throws IOException {        }    });复制代码

2.Request

public static class Builder {    HttpUrl url;    String method;    Headers.Builder headers;    RequestBody body;    Object tag;    public Builder() {      this.method = "GET";      this.headers = new Headers.Builder();    }    ......}复制代码

Request主要功能是将请求的所有特性封装到一起,从它的成员变量可以看到主要包括url,method,headers,body,tag(主要用来标识这个请求,方便后面来延迟或者取消标识的请求)

3.Call

3.1 Call的创建

public Call newCall(Request request) {    return RealCall.newRealCall(this, request, false /* for web socket */); }复制代码

用的是Call的实现类RealCall。关于Call的解释

/** * A call is a request that has been prepared for execution. A call can be canceled. As this object * represents a single request/response pair (stream), it cannot be executed twice. */public interface Call extends Cloneable {  Request request();  /**   * Invokes the request immediately, and blocks until the response can be processed or is in   * error.   *   * 

To avoid leaking resources callers should close the {

@link Response} which in turn will * close the underlying {
@link ResponseBody}. * *

@{code   *   *   // ensure the response (and underlying response body) is closed   *   try (Response response = client.newCall(request).execute()) {   *     ...   *   }   *   * }
* *

The caller may read the response body with the response's {

@link Response#body} method. To * avoid leaking resources callers must {
@linkplain ResponseBody close the response body} or the * Response. * *

Note that transport-layer success (receiving a HTTP response code, headers and body) does * not necessarily indicate application-layer success: {

@code response} may still indicate an * unhappy HTTP response code like 404 or 500. * * @throws IOException if the request could not be executed due to cancellation, a connectivity * problem or timeout. Because networks can fail during an exchange, it is possible that the * remote server accepted the request before the failure. * @throws IllegalStateException when the call has already been executed. */ Response execute() throws IOException; /** * Schedules the request to be executed at some point in the future. * *

The {

@link OkHttpClient#dispatcher dispatcher} defines when the request will run: usually * immediately unless there are several other requests currently being executed. * *

This client will later call back {

@code responseCallback} with either an HTTP response or a * failure exception. * * @throws IllegalStateException when the call has already been executed. */ void enqueue(Callback responseCallback); /** Cancels the request, if possible. Requests that are already complete cannot be canceled. */ void cancel(); /** * Returns true if this call has been either {
@linkplain #execute() executed} or {
@linkplain * #enqueue(Callback) enqueued}. It is an error to execute a call more than once. */ boolean isExecuted(); boolean isCanceled(); /** * Create a new, identical call to this one which can be enqueued or executed even if this call * has already been. */ Call clone(); interface Factory { Call newCall(Request request); }}复制代码

  • Call可以被取消,一个Call最多只能被执行一次
  • Response execute()方法:同步执行,没有response前会阻塞
  • void enqueue(Callback responseCallback)方法:异步执行,执行结果在Callback回调
  • void cancel()方法:取消一个尚未之行结束的request,不过request执行完毕后就不能被取消
  • boolean isExecuted()方法:请求是否已经执行
  • boolean isCanceled()方法:请求是否已经被取消
  • Call clone()方法:复制一个新的Call,并且可以被重新执行,哪怕被复制的Call已经执行

3.2 Call的执行

直接看RealCall的enqueue方法

public void enqueue(Callback responseCallback) {    synchronized (this) {      if (executed) throw new IllegalStateException("Already Executed");      executed = true;    }    captureCallStackTrace();    eventListener.callStart(this);    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);    } }复制代码

正在执行的所有call请求数不能超过maxRequests(64)个,并且同一host的请求不能超过maxRequestsPerHost(5)个,否则就加到等待队列readyAsyncCalls中

public synchronized ExecutorService executorService() {    if (executorService == null) {      executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,          new SynchronousQueue
(), Util.threadFactory("OkHttp Dispatcher", false)); } return executorService; }复制代码

最后是通过线程池ThreadPoolExecutor来执行AsyncCall的,AsyncCall继承自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();}复制代码

本质就是用线程池执行了一个Runnable.NamedRunnable的run方法中最终会执行execute方法 AsyncCall的execute方法

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 {          eventListener.callFailed(RealCall.this, e);          responseCallback.onFailure(RealCall.this, e);        }      } finally {        client.dispatcher().finished(this);      }    }复制代码

通过getResponseWithInterceptorChain方法拿到请求结果

转载于:https://juejin.im/post/5cc7fa0cf265da03a630e4d5

你可能感兴趣的文章
阻止了 WannaCry 扩散的研究员承认开发恶意软件
查看>>
云栖大会首设“科技脱贫”专场 ,20张会场门票等你来拿!
查看>>
ZLG 发布开源 GUI 引擎 AWTK
查看>>
一个不可思议的MySQL慢查分析与解决
查看>>
[Cake] 0.C#Make自动化构建-简介
查看>>
《TCP/IP协议》- TCP协议知识目录
查看>>
详尽! Win10安装Java8+Tomcat9!
查看>>
1127
查看>>
一次痛的经历
查看>>
智能运维(AIOps)时代开启,一文帮你快速了解其定义与发展现状
查看>>
第1讲 快速入门 《Kotlin 极简教程 》
查看>>
[Hadoop]MapReducer工作过程
查看>>
VMware PowerCli批量实现虚拟机快照备份
查看>>
小程聊微服务-基于dubbo的mock测试系统
查看>>
在阿里云服务器使用scrapyd部署scrapy项目
查看>>
业界 | 从观望者到变革者:给新媒体的AI解决方案
查看>>
利用 CSS 变量实现令人震惊的悬浮效果
查看>>
爬虫入门之handler与opener(三)
查看>>
Linux Kernel 5.2 将进一步支持 AMD FreeSync
查看>>
Java CompletableFuture:thenCompose (3)
查看>>