Okhttp3源码分析

okhttp3源码分析之AsyncTimeout 继承自Timeout, 使后台线程在发生超时时准确执行操作。用来实现本机不支持的超时。 公开方法: final void enter() 调用了private static synchronized void scheduleTimeout,确定链表关系(当前node上个的next和this的header前后关系)。 private static synchronized void s... 阅读详情

okhttp3源码分析基于okhttp3.10.0。

关于okhttp的特点及相关功能的介绍可以查看官网的介绍:

  1. http://square.github.io/okhttp/
  2. https://github.com/square/okhttp/wiki

基本使用

使用okhttp发起一次网络请求,只需要以下流程即可:

  1. 创建OkHttpClient
  2. 创建Request对象
  3. 创建一个Call对象,用于发起请求
  4. 发起网络请求(同步请求execute; 异步请求enqueue)

代码演示:

public void request()  {

    // 1、创建OkHttpClient
    OkHttpClient okHttpClient = new OkHttpClient();

    // 2、创建Request请求
    Request request = new Request.Builder()
            .url("https://blog.youkuaiyun.com/kaifa1321")
            .build();

    // 3、创建一个Call对象,用于发起请求
    Call call = okHttpClient.newCall(request);

    // 4、发起网络请求

    // 4.1、执行一个同步请求,获取Response
    Response response = call.execute();

    // 4.2、执行一个异步请求,通过Callback获取Response
    call.enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {}

        @Override
        public void onResponse(Call call, Response response) throws IOException {
            // 处理响应
            String string = response.body().string();
        }
    });
}

源码分析

针对上文中提到的okhttp的使用流程,这里将对这些流程的源码逐一分析。

创建OkHttpClient实例

OkHttpClient对象的创建,okhttp中提供了两种方式:

  • 通过无参数构造方法创建OkHttpClient
  • 通过OkHttpClient内部类Builder,使用建造者模式创建OkHttpClient实例
// 1、构造方法创建OkHttpClient
OkHttpClient okHttpClient = new OkHttpClient();

// 2、通过Builder创建OkHttpClient
OkHttpClient okHttpClient = new OkHttpClient.Builder()
        .addInterceptor(null)
        .cache(null)
        .build();

OkHttpClient实例化过程

这里看下OkHttpClient的构造方法:

public OkHttpClient() {
    this(new OkHttpClient());
}

OkHttpClient(Builder builder) {
    // 这不是该方法的完成代码,具体请看源码
    this.dispatcher = builder.dispatcher;
    this.interceptors = Util.immutableList(builder.interceptors);
    this.cache = builder.cache;
    this.internalCache = builder.internalCache;

    this.connectTimeout = builder.connectTimeout;
    this.readTimeout = builder.readTimeout;
    this.writeTimeout = builder.writeTimeout;

}

通过上面源码可以得知,OkHttpClient的无参构造方法最后也是通过创建一个Builder对象,完成OkHttpClient的实例化。其实无参参构造方法实例化OkHttpClient和通过Builder.build()方法实例化原理上完全一样,都是通过创建一个Builder对象初始化OkHttpClient,唯一不同的是Builder对象参数(系统默认和开发者自己设置)

这里看下Builder.build()方法

public OkHttpClient build() {
   // 这个this就是Builder对象本身
  return new OkHttpClient(this);
}

OkHttpClient通过建造者模式完成实例化,这种创建模式在okhttp中有使用非常多,例如Request、Response的创建都使用了该模式。

定制化OkHttpClient实例

在okhttp的官网中建议开发者在使用okhttp时,OkHttpClient的实例最好是通过单一实例,这样可以更好的管理okhttp的连接池和线程池。
但是,一般在应用开发中,会遇到一些特殊的请求,比如添加一个拦截器、添加缓存等的操作。如果我们直接修改单一实例的OkHttpClient,这样势必会影响其他的请求,okhttp也考虑到了这种情况,也给我们提供给了定制化OkHttpClient实例的方法newBuidler。

  OkHttpClient client = new OkHttpClient();
  client.newBuilder()
          .readTimeout(10, TimeUnit.SECONDS)
          .writeTimeout(10, TimeUnit.SECONDS)
          .build();

这里看下newBuilder方法

  public Builder newBuilder() {
    // this就是OkHttpClient单一实例
    return new Builder(this);
  }

通过已有的OkHttpClient实例创建一个新的Builder对象,这个Builder对象默认持有原来OkHttpClient实例的属性,这样就可以完全复用存在的OkHttpClient的相关设置,只需要对一些特定的属性做出修改即可。例如readTimeout,writeTimeout等。

创建Request对象

Request对象的主要作用就是封装Http请求的主要参数,这些参数包括:

  • url
  • http请求方式:GET、POST等
  • 请求体RequestBody,POST等请求方式时需要
  • http请求头

Request对象和OkHttpClient一样,也是通过建造者模式创建的.

创建Request对象:

    Request request = new Request.Builder()
        .url("https://api.github.com/repos/square/okhttp/issues")
        .header("User-Agent", "OkHttp Headers.java")
        .addHeader("Accept", "application/json; q=0.5")
        .addHeader("Accept", "application/vnd.github.v3+json")
        .post(RequestBody.create(MediaType, File))
        .build();

Request的创建流程相对简单,在上面中基本能够一目了然,这里就不做过多的介绍了。

在上面的代码示例中,需要注意的就是在Request中添加Header请求头的方法header()和addHeader()

在Request的源码中也对两个方法做了具体说明:

  • header():设置唯一的请求头键值对,如果存在相同name的请求头,value将会被覆盖。
  • addHeader():对相同name的请求头可以设置多个Value

RequestBody

在Request的创建过程中,如果该Request是一个POST请求,那么需要为该Request创建一个请求体RequestBody,RequestBody的创建需要调用静态方法create(),RequestBody中有几个重载的create()方法,主要针对不同的请求体类型创建请求体实例。

这里看下RequestBody类的具体内容。

    public abstract class RequestBody {
        // 请求体类型
        public abstract @Nullable MediaType contentType();

        // 请求体长度
        public long contentLength() throws IOException {
            return -1;
        }


        // 将请求体内容写到sink,sink是okio中的类,可以理解成输出流
        public abstract void writeTo(BufferedSink sink) throws IOException;

        /**
         * 创建一个请求体,
         */
        public static RequestBody create(@Nullable MediaType contentType, String content) {
            // 使用UTF-8编码
            Charset charset = Util.UTF_8;
            if (contentType != null) {
                charset = contentType.charset();
                if (charset == null) {
                    charset = Util.UTF_8;
                    contentType = MediaType.parse(contentType + "; charset=utf-8");
                }
            }
            byte[] bytes = content.getBytes(charset);
            return create(contentType, bytes);
        }

        /**
         * 创建请求体
         */
        public static RequestBody create(
                final @Nullable MediaType contentType, final ByteString content) {
            return new RequestBody() {
                @Override public @Nullable MediaType contentType() {
                    return contentType;
                }

                @Override public long contentLength() throws IOException {
                    return content.size();
                }

                @Override public void writeTo(BufferedSink sink) throws IOException {
                    sink.write(content);
                }
            };
        }

        /**
         * 创建请求体
         */
        public static RequestBody create(final @Nullable MediaType contentType, final byte[] content) {
            return create(contentType, content, 0, content.length);
        }


        /**
         * 创建请求体
         */
        public static RequestBody create(final @Nullable MediaType contentType, final byte[] content,
                                         final int offset, final int byteCount) {
            if (content == null) throw new NullPointerException("content == null");
            Util.checkOffsetAndCount(content.length, offset, byteCount);
            return new RequestBody() {
                @Override public @Nullable MediaType contentType() {
                    return contentType;
                }

                @Override public long contentLength() {
                    return byteCount;
                }

                @Override public void writeTo(BufferedSink sink) throws IOException {
                    // 将请求体内容写出到sink
                    sink.write(content, offset, byteCount);
                }
            };
        }

        /**
         * 创建一个请求体,请求体类型为file,一般文件上传时使用
         */
        public static RequestBody create(final @Nullable MediaType contentType, final File file) {
            if (file == null) throw new NullPointerException("content == null");

            return new RequestBody() {
                @Override public @Nullable MediaType contentType() {
                    return contentType;
                }

                @Override public long contentLength() {
                    return file.length();
                }

                @Override public void writeTo(BufferedSink sink) throws IOException {
                    Source source = null;
                    try {
                        source = Okio.source(file);
                        sink.writeAll(source);
                    } finally {
                        Util.closeQuietly(source);
                    }
                }
            };
        }
    }

这里给出核心代码


public static class Builder {

    Headers.Builder headers;

    public Builder header(String name, String value) {
      headers.set(name, value);
      return this;
    }

    public Builder addHeader(String name, String value) {
      headers.add(name, value);
      return this;
    }
}


public final class Headers {

    final List<String> namesAndValues = new ArrayList<>(20);

    // 添加一组键值对
    public Builder add(String name, String value) {
      checkNameAndValue(name, value);
      return addLenient(name, value);
    }


    // 添加唯一键值对
    public Builder set(String name, String value) {
      checkNameAndValue(name, value);
      // 如果存在,移除
      removeAll(name);
      addLenient(name, value);
      return this;
    }

    // 添加到list集合中
    Builder addLenient(String name, String value) {
      namesAndValues.add(name);
      namesAndValues.add(value.trim());
      return this;
    }
}

创建Call对象

// 3、创建一个Call启动请求
Call call = okHttpClient.newCall(request);

在okHttpClient.newCall()方法方法中通过调用RealCall.newRealCall()方法获取一个Call(RealCall)实例。

@Override 
public Call newCall(Request request) {
    // 获取一个Call(RealCall)对象
    return RealCall.newRealCall(this, request, false /* for web socket */);
}

发起网络请求

详见下节:Call接口及实现类RealCall

Call接口及实现类RealCall

Call

Call接口,主要实现网络请求调用。

  • 通过execute方法实现同步请求获取请求响应。
  • 通过enqueue方法实现异步请求通过CallBack回调获取请求响应。


Call接口源码

public interface Call extends Cloneable {

  // 返回原始请求对象
  Request request();

  // 同步请求
  Response execute() throws IOException;

  // 异步请求
  void enqueue(Callback responseCallback);

  // 取消请求
  void cancel();

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

  // 是否取消
  boolean isCanceled();

  Call clone();

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

RealCall

RealCall是Call接口的唯一实现类,因此okhttp的网络请求都是在RealCall类里面实现的。
所以这里将会对RealCall做详细的分析。

创建RealCall实例

在上文中说到,RealCall对象是在okHttpClient.newCall()方法中通过调用RealCall.newRealCall方法完成创建的。

这里看下RealCall.newRealCall()方法:

static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
    // Safely publish the Call instance to the EventListener.
    RealCall call = new RealCall(client, originalRequest, forWebSocket);
    call.eventListener = client.eventListenerFactory().create(call);
    return call;
}

在该方法中,主要就是通过构造方法完成RealCall对象的创建,并且该RealCall对象持有了OkHttpClient和Requst实例。

RealCall对象创建以后,就可以开始正式的网络请求了,这里主要分为同步请求和异步请求。


// 执行一个同步请求,获取Response
try {
    Response response = call.execute();
} catch (IOException e) {
    e.printStackTrace();
}


// 执行一个异步请求,通过Callback获取Response
call.enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {}

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        // 处理响应
        String string = response.body().string();
    }
});

这里对这两个请求方式一一分析。

execute同步请求

RealCall.execute()

  public Response execute() throws IOException {

    // 1、首先判断该Call是否执行
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace();
    eventListener.callStart(this);


    try {

      // 2、调用OkHttpClient中的dispatcher的executed方法
      client.dispatcher().executed(this);

      // 3、通过拦截器链获取http响应Response
      Response result = getResponseWithInterceptorChain();
      if (result == null) throw new IOException("Canceled");
      return result;
    } catch (IOException e) {
      eventListener.callFailed(this, e);
      throw e;
    } finally {

      // 4、结束请求,从同步请求队列中移除该Call
      client.dispatcher().finished(this);
    }
  }

在execute()方法中主要完成了以下功能:

  1. 首先,判断该请求是否被执行,一个Call智能执行一次
  2. 其次,调用OkHttpClient.dispatcher对象的executed方法将请求放入到同步请求队列中。
  3. 然后,通过okhttp中的拦截器链获取http响应
  4. 最后,通过调用OkHttpClient.dispatcher对象的finished()方法结束请求(这个将在下文中Dispatcher分发器中具体分析)

在同步请求中,最终通过RealCall.getResponseWithInterceptorChain()方法获取响应,通过这个方法的名字也能知道该方法的作用:通过拦截器链获取响应。

核心功能:Dispatcher分发器。
这个将在后续的章节中做具体的分析,这里只需要知道同步异步请求最终都是在Dispatcher请求分发器中完成的即可


核心功能:Interceptor拦截器。
这个将在后续的章节中做具体的分析,这里只需要知道获取Http响应是通过Intercepter拦截器中完成的即可。

enqueue异步请求

RealCall.enqueue(Callback)

  @Override 
  public void enqueue(Callback responseCallback) {

        // 1、首先判断该Call是否执行
        synchronized (this) {
          if (executed) throw new IllegalStateException("Already Executed");
          executed = true;
        }
        captureCallStackTrace();
        eventListener.callStart(this);

        // 创建一个AsyncCall对象,将对象放入到异步队列中
        client.dispatcher().enqueue(new AsyncCall(responseCallback));
  }

在enqueue()方法中主要完成了以下功能:

  1. 首先,判断该请求是否被执行,一个Call只能执行一次
  2. 然后,调用OkHttpClient.dispatcher对象的enqueue()方法将请求添加到异步请求队列中被执行。

在上面enqueue方法中,最后执行client.dispatcher().enqueue(new AsyncCall(responseCallback))时,创建了一个AsyncCall对象。

这里需要对这个AsyncCall做进一步分析。

AsyncCall

AsyncCall是RealCall的一个内部类,AsyncCall继承自NamedRunnable,而NamedRunnable实现了Runnable接口,所以AsyncCall主要作用就是实现Runnable接口。

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

NamedRunnable是一个抽象类,实现了Runnable接口,在该类中定义了一个抽象方法execute(),主要就是实现具体的异步操作,这里对该类就不做过多解释了。

接下来主要看下NamedRunnable的子类AsyncCall

AsyncCall

  final class AsyncCall extends NamedRunnable {
    private final Callback responseCallback;

    AsyncCall(Callback responseCallback) {
      super("OkHttp %s", redactedUrl());
      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 {
          eventListener.callFailed(RealCall.this, e);
          responseCallback.onFailure(RealCall.this, e);
        }
      } finally {
        // 结束异步请求,让线程池继续处理其他等待请求
        client.dispatcher().finished(this);
      }
    }
  }

在AsyncCall的execute方法中主要作用就两个:

  • 通过RealCall.getResponseWithInterceptorChain()方法获取请求响应,这个和同步请求方法中调用的是同一个方法。

  • 在获取网络响应后,通过调动 client.dispatcher().finished(this)将该请求从异步请求队列中移除,表示该请求已经处理完,并让线程池执行其他异步等待队列中的请求。

看到这里想必你就清楚了,异步处理流程和上文中RealCall.execute()同步请求是完全一样的,唯一不同的就是一个是在主线程中完成的,一个是在子线程(AsyncCall)中完成的。

关于Dispatcher分发器和Interceptor拦截器将在下面章节中具体介绍。

OkHttp3源码分析-BridgeInterceptor BridgeInterceptor BridgeInterceptor主要用于网络请求的构建,和响应的解析。 public final class BridgeInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { ... 阅读详情

相关推荐

OKHttp3源码分析——学习笔记

文章目录1. HttpClient与HttpUrlConnection的区别2. OKHttp源码分析使用步骤:dispatcher任务调度器,Request请求RealCallAsyncCall3. OKHttp架构分析1. 异步请求线程池, Dispather2. 连接池清理线程池- ConnectionPool3. 缓存整理线程池 DisLruCache4. Http2异步事务线程池, ht...

Sincerity_的博客 1380

OkHttp3源码详解

OkHttp3源码详解

QG 1915

从零到一:手把手教你用C#开发AGV调度系统(附避坑指南)

本文详细介绍了如何使用C#开发高效的AGV调度系统,涵盖从环境搭建到核心算法实现的完整流程。重点解析了动态路径规划、多机协同等关键技术,并提供了实用的避坑指南和性能优化建议,帮助开发者快速构建工业级车辆控制调度系统。

blockchain9miner的博客 742

OkHttp3源码解析 - 请求流程

在Android蛮荒年代,我们做网络请求通常会选用HttpURLConnection或者Apache HTTP Client,这两者均支持HTTPS、流的上传和下载、配置超时和连接池等特性,但随着业务场景的复杂化以及对流量消耗的优化需求,OkHttp应运而生。现在谈起网络请求,大家肯定下意识想到的就是 okHttp 或者 retrofit 这样的三方请求库。

Android百晓生的博客 1072

车载以太网SOMEIP入门必看:从服务发现到事件订阅,一次搞懂三种核心通信模式(附报文实例)

本文深入解析车载以太网SOME/IP的三种核心通信模式:服务发现、方法调用和事件订阅,通过真实报文实例和仿真工具演示,帮助开发者快速掌握这一关键技术。文章特别强调服务发现机制的基础作用,并详细介绍了Request/Response与Fire&Forget两种方法调用模式的应用场景,为智能汽车网络通信开发提供实用指南。

weixin_30955617的博客 111

FinRL实战:5步搞定股票量化交易策略(附Python代码)

本文详细介绍了如何使用FinRL框架,通过5个步骤构建基于深度强化学习的股票量化交易策略。内容涵盖从环境搭建、数据获取与预处理,到交易环境构建、模型训练(如PPO算法),以及策略回测评估与优化的完整流程,并提供了可运行的Python代码示例,帮助读者快速入门AI驱动的量化交易。

weixin_29062865的博客 627

OkHttp3源码解析(高工视角)

本文解读的OkHttp版本是3.14.9,拉取自master分支的parent-3.14.9(tag);这是OkHttp团队将okhttp项目migrate to Kotlin前的最后一个版本。java是最...算了不拉仇恨了^_^。 1.http/1.1 2.http/2.0

m0_37840695的博客 843

获取本机正版windows10激活密钥,以及正版office

本方法面向的是以前买过笔记本电脑给你预装了正版系统,激活了正版office(一般是家庭版)的情况,其他情况请自行尝试。

qq_45774917的博客 2万+

OkHttp3源码解析--设计模式

看到这篇文章的人不知道有多少是和我一样的Android程序员。35岁,这是我们这个行业普遍的失业高发阶段,这种情况下如果还不提升自己的技能,进阶发展,我想,很可能就是本行业的职业生涯的终点了。我们要有危机意识,切莫等到一切都成定局时才开始追悔莫及。只要有规划的,有系统地学习,进阶提升自己并不难,给自己多充一点电,你才能走的更远。千里之行始于足下。这是上小学时,那种一元钱一个的日记本上每一页下面都印刷有的一句话,当时只觉得这句话很短,后来渐渐长大才慢慢明白这句话的真正的含义。

2301_79985012的博客 891

SAP-ABAP:新手入门篇——从0到1写出你的第一个ABAP Hello World程序并完成调试运行

本文是ABAP开发入门指南,详细介绍如何创建并运行第一个"Hello World"程序。主要内容包括:通过SE38事务码进入ABAP编辑器;创建以Z/Y开头的程序并保存为本地对象;编写简单的WRITE输出语句;完成语法检查、激活和执行流程;以及初步体验调试功能。文章特别强调ABAP开发的规范要求,如程序命名规则、激活与保存的区别等,并提供了详细的步骤说明和常见问题提示,帮助零基础开发者快速上手ABAP编程。

baidu_35680696的博客 480

基于RK3588的YOLOv11目标检测NPU加速系统设计与实现——模型转换(RKNN)、量化与板端部署全流程(含环境搭建与疑难解析)

而RK3588芯片则是一款性能强劲的边缘计算芯片,将YOLOv11部署在RK3588上,可实现本地化的智能检测应用,比如工业质检中的产品缺陷识别、安防领域的异常行为监测等。比如,优化模型的推理速度,可通过调整模型的输入尺寸、使用更高效的推理框架等方式实现;可以使用RK提供的量化工具来完成这一过程,按照工具的使用说明,对ONNX模型进行量化,生成适用于RK3588的模型文件。现在,你已经掌握了从环境搭建到模型部署的全流程,赶快动手实践,让YOLOv11在RK3588上绽放智能光彩,打造属于你的AI应用吧!

m0_71589036的博客 45

OKHttp3 源码阅读 - Kotlin版本

OKHttp 是由 Square 公司开源的,广泛应用于 Android 开发中,并且是 Retrofit 的底层实现。它是一个高效的 HTTP 客户端,适用于 Android 和 Java 应用程序。它支持 HTTP/2、连接池、GZIP 压缩、缓存等功能,能够帮助开发者更高效地处理网络请求。从 Android 4.4 开始 HttpURLConnection 的底层实现采用的是OKHttp。OkHttp是一个功能强大且灵活的HTTP客户端库,适用于各种网络请求场景。

Bonnie_cat的博客 1158

数据库系统工程师软考备战:第三篇 - SQL语言深入解析与应用

​​创建表​​​修改表​​​删除表​。

Programming Talk 122

okhttp3 底层源码分析

okhttp3源码分析之请求流程:链接地址 okhttp3源码分析之拦截器:链接地址

悟-静的博客 553

【云原生技术】sonar的官方web接口,获取质量阀结果的接口

以下是一个示例思路,说明如何调用 SonarQube 的质量阀查询接口并在前端展示“哪些条件没过”。假设前端使用 AJAX 或 fetch 从后端接口拿到 SonarQube 返回的 JSON(或直接前端请求 SonarQube API),前端再把解析结果展示给用户。测试覆盖率 (Coverage) 当前仅有 60%,未满足最低 80% 的要求,需要补充测试或优化以提升覆盖率。接口),就会返回相应的质量阀状态信息;里使用它来查询当前质量阀(质量门)的状态。,你用它即可获取该次分析的质量阀状态。

weixin_46453070的博客 1279

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

【OkHttp3源码分析】

OkHttp3源码分析

u012632105的博客 121

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

OkHttp3源码分析-缓存与CacheInterceptor

基本结构 CacheInterceptor依赖两个关键类,一个是CacheStrategy,一个是InternalCache。 CacheStrategy采用的是简单工厂模式(其实只是抽象工厂的特例),此类用于判定使用缓存,网络还是二者都使用。 InternalCache基本不会自己去设置,会使用Cache中的InternalCache的结构,而Cache实际上是通过DiskLruCache实现...

wfeii的博客 600

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Android OkHttp3源码分析

title: Android OkHttp3源码分析 date: 2019-06-03 21:16:50 tags: Android第三方框架 文章目录title: Android OkHttp3源码分析 date: 2019-06-03 21:16:50 tags: Android第三方框架Android OkHttp3源码分析介绍源码分析简单使用OkHttpClient的创建Request的...

hesheng1024的博客 2663

OKHttp3.14源码分析记录

OkHttp是一个处理网络请求的开源项目,是Android端最火热的轻量级框架,由移动支付Square公司贡献用于替代HttpUrlConnection和Apache HttpClient。随着OkHttp的不断成熟,越来越多的Android开发者使用OkHttp作为网络框架。 1、首先推荐看以下几篇文章《OkHttp 3.7源码分析》,了解OKHttp的整体框架以及重要的拦截器模块。 OkHttp源码分析——整体架构 OkHttp源码分析——拦截器 OkHttp源码分析...

天空24的专栏 388

OkHttp3源码分析

基本用法 平常开发Android App的时候,经常用到OkHttp,不能只停留在会用的阶段,还要知道其原理。今天就来分析一下OkHttp3的源码。 POST请求的基本用法如下: OkHttpClient client = new OkHttpClient.Builder().build(); FormBody body = new FormBody.Builder() ...

acaixuediannao的专栏 1023

Okhttp3源码分析之三

从Okhttp3源码分析之一可知,调用Call的enqueue执行最终的请求 //1.创建OkHttpClient对象 OkHttpClient okHttpClient = new OkHttpClient(); //2.创建Request对象,设置一个url地址(百度地址),设置请求方式。 Request request = ...

jy专栏 233

Okhttp3源码分析之一

一、OKHTTP简介 OKHttp是一个处理网络请求的开源项目OKHttp GitHub地址 OKHttp优点 支持HTTP2/SPDY(SPDY是Google开发的基于TCP的传输层协议,用以最小化网络延迟,提升网络速度,优化用户的网络使用体验。) socket自动选择最好路线,并支持自动重连,拥有自动维护的socket连接池,减少握手次数,减少了请求延迟,共享Socket,减少对服务器...

jy专栏 334

okhttp3源码分析之请求流程

okhttp3源码分析之请求流程 前言 在Android开发中,当下最火的网络请求框架莫过于okhttp和retrofit,它们都是square公司的产品,两个都是非常优秀开源库,值得我们去阅读它们的源码,学习它们的设计理念,但其实retrofit底层还是用okhttp来发起网络请求的,所以深入理解了okhttp也就深入理解了retrofit,它们的源码阅读顺序应该是先看okhttp,我在retr...

Kelvin的专栏 366

Okhttp3源码分析之二

从Okhttp3源码解析之一了解到,使用OKHTTP执行一个http请求需要四步 一、接下来分析一下Request: public final class Request { final HttpUrl url;//请求地址 final String method;//请求模式post、get……等 final Headers headers;//请求头 final @Nul...

jy专栏 275
上一篇: UML 类图和时序图
下一篇: Okhttp3源码分析(2) Dispatcher分发器
Kerwin zhang
博客等级 码龄12年 21粉丝 28原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值