OKHTTP内部流程

OkHttp源码解析(很细 很长) 使用方法 使用方法十分简单,分别创建一个OkHttpClient对象,一个Request对象,然后利用他们创建一个Call对象,最后调用同步请求execute()方法或者异步请求enqueue()方法来拿到Response。 private final OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url("https://github.com/") .b 阅读详情

最近无聊看了一下OKHTTP源码,大致了解了一下我们使用OKHTTP发送网络请求之后,内部都发生了什么。简单说一下哈

我们正常发送一个get请求如下
 OkHttpClient client = new OkHttpClient();
 Request request = new Request.Builder().get().url(url).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 {
     }
 });
  @Override 
  public void enqueue(Callback responseCallback) {
   // ......
   client.dispatcher().enqueue(new AsyncCall(responseCallback));
 }

client.newCall创建了一个RealCall对象,通过enqueue方法调用client.dispatcher().enqueue(new AsyncCall(responseCallback)); 将封装好的异步请求交给Dispatcher

查看Dispatcher怎么分发我们的请求
  synchronized void enqueue(AsyncCall call) {
    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
      runningAsyncCalls.add(call);
      executorService().execute(call);
    } else {
      readyAsyncCalls.add(call);
    }
  }

可以看出来,Dispatcher维护了两个队列runningAsyncCalls和readyAsyncCalls。

  1. 如果正在运行的队列小于maxRequests也就是64个,并且请求同一个host的数量小于maxRequestsPerHost也就是5个。那么直接将该请求加入到runningAsyncCalls队列,立刻执行。
  2. 如果不满足条件1,那么将该请求加入到readyAsyncCalls队列
看一下如何执行runningAsyncCalls中的请求

通过executorService().execute(call);执行该请求任务。executorService()创建了一个线程池,使用的是不存储元素的阻塞队列SynchronousQueue,也就是没有核心线程,队列不存储请求,当有请求时直接执行。

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

然后我们就要看一下AsyncCall了。

  • AsyncCall继承自NamedRunnable,线程池执行execute()方法时,通过NamedRunnable调用AsyncCall重写的execute方法。
  • 通过getResponseWithInterceptorChain()方法获取到response之后,将response返回。
  • 在finally执行 client.dispatcher().finished(this)方法,表明该请求执行完成
final class AsyncCall extends NamedRunnable {
    private final Callback responseCallback;
	// ......
    @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) {
          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);
      }
    }
  }
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();
}
我们看一下一个请求执行完成以后,还有哪些操作
  • RealCall在执行完成之后会在finally执行 client.dispatcher().finished(this)方法,finish方法会将当前执行过的请求从立即执行队列中移除,然后通过 promoteCalls()方法看是否有任务可以从准备执行队列添加到立即执行队列。
  • 当直接运行的队列小于最大值64,并且准备执行队列中仍有请求时,遍历准备执行队列进行判断
    • 判断如果加上当前请求,直接运行队列请求统一host数量仍然小于5,就把当前请求加入到直接执行队列,立刻执行,此时如果直接运行队列数量大于最大值64,那就中断循环。
    • 判断如果加上当前请求,直接运行队列请求统一host数量如果大于5,就跳过当前请求。当前请求需要等下一个任务执行完成之后,再次调用promoteCalls()方法进行判断。
    • 执行完判断之后,如果立即执行队列达到最大值64,那么就不再继续遍历。如果没有达到最大值64,那就接着遍历,继续判断,继续往立即执行队列中添加
  void finished(AsyncCall call) {
    finished(runningAsyncCalls, call, true);
  }

  void finished(RealCall call) {
    finished(runningSyncCalls, call, false);
  }
  
  private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
	// ...
    synchronized (this) {
      // 移除执行过的请求
      if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
       // 去准备执行队列,看是否要添加请求到立即执行队列
      if (promoteCalls) promoteCalls();
      // ...
    }
  }
  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.
    }
  }
OkHttp 源码分析 OkHttp的核心组件包括OkHttpClient、Call、Interceptor、Dispatcher和ConnectionPool等。通过这些组件,OkHttp实现了高效的请求管理、连接复用和响应缓存等功能。开发者可以自定义拦截器来添加额外的处理逻辑。@Override通过分析OkHttp的核心组件及其源码,可以看出OkHttp在设计上注重高效、灵活和可扩展性。了解这些原理有助于更好地使用和优化OkHttp,以满足不同的应用需求。 阅读详情

相关推荐

OKHttp 源码解析(一)

目前大多数的网络框架都是使用 OKHttp ,Retrofit 也是基于 OKHttp,OKHttp 使用简单,但出现的问题不少,也借此机会了解一下 OKHttp 的源码。本文的 OKHttp 源码基于 3.4.2 版本。通过newCall访问RealCall如果是同步请求,调用execute如果是异步请求,调用enqueue以上都是通过Dispatcher将Call添加到队列调用遍历拦截器,执行请求获取结果将Call从 队列移除。

MarinaTsang的博客 673

OKhttp源码

Okhttp的顺序源码解析及其自定义拦截器

qq_65337539的博客 933

OkHttp原理分析总结

OkHttp原理解析 OkHttp 3.10.0版本,最新OkHttp为:4.0.1逻辑与3版本并没有太大变化,但是改为kotlin实现。 OkHttp介绍 OkHttp是当下Android使用最频繁的网络请求框架,由Square公司开源。Google在Android4.4以后开始将源码中的HttpURLConnection底层实现替换为OKHttp,同时现在流行的Retrofit框架底层同样...

天亮了的博客 1万+

OkHttp源码解析(小白必看,建议收藏

进入下一个调用dispatcher().enqueue();//运行中的队列} else {//等待中的队列,可看成支线相应的对象如下://可以很明显看出是添加到了runningAsyncCalls,readyAsyncCalls中此方法的大致内容:对请求的入队做了一些限制,若正在执行的请求数量小于最大值(默认64),并且此请求所属主机的正在执行任务小于最大值(默认5),就加入正在运行的队列并通过线程池来执行该任务,否则加入准备执行队列中。

m0_58269520的博客 1512

“深入交流“系列:Okhttp(一)请求流程解析

Okhttp请求流程源码解析 前言 最近发现以前学习过的好多东西,都忘记了,所以打算复习一次,并且通过输出博客来加深印象。Okhttp准备分成两篇文章来讲解,这篇文章主要叙述一下Okhttp的整体请求流程,第二篇文章则讲述一下Okhttp中极为重要的拦截器。“深入交流”系列打算从一些第三方框架源码或者FrameWork层源码入手,进行"深入"的交流,会持续输出下去,敬请期待。 1、Okhttp的同步请求和异步请求 在分析Okhttp的源码之前,我们首先了解一下Okhttp最基本的实现一次网络请求的方式。 O

军火库 2192

全国充电站分布数据

CnOpenData推出的充电站数据覆盖全国34个省份的3万条数据,包含充电站名称、省份名称、省份代码、商圈、经纬度等地理信息以及商业类型、评分、消费等衍生信息,能为城市规划、环境科学、市场分析、技术发展和社会经济研究等多个领域提供宝贵的数据支持。

Sunny9qx的博客 4024

OkHttp内部流程解析

最近在看okhttp源码,这个流程度总结的很棒,记录一下~

weixin_38251977的博客 291

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

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

weixin_30955617的博客 111

OkHttp源码流程简单分析

增加了对空闲链接的清理流程

Android_Jay的博客 963

RandLA-Net 调通代码1:Windows 11 + Tensorflow 2.4 + S3DIS数据集【踩坑+填坑】

TF不上进啊,学学pytorch

累了就要打游戏 2480

精通DC-DC变换器:Boost升压电路全解析

Boost升压变换器是一种将低直流电压转换为高直流电压的常用电路。其核心工作原理是通过电感储能:开关导通时电感充电,关断时电感与电源串联向负载供电。关键公式表明输出电压Vo=Vi/(1-D),占空比D越大,升压比越高。变换器工作时会产生电感电流纹波和输出电压纹波,需合理选择电感和电容参数。开关管和二极管需承受完整的输出电压,对元器件选型要求较高。理解这些原理是设计高效升压电源的基础。

2511_92918351的博客 3706

Android OkHttp 内部原理深度分析

OkHttp 是 Android 和 Java 应用中最流行的 HTTP 客户端之一,其内部设计精妙,性能优异。下面我将从核心架构、关键组件和工作流程三个方面深入分析其内部原理。

专注于移动开发的干货分享。提供高效解决方案、避坑指南与前沿技术解析。为开发者创造价值。 1125

蓝桥杯单片机学习13——NE555方波发生器&频率测量

NE555详解、引脚图介绍、原理图及工作原理讲解、方波产生的原理、定时器测量频率的原理及使用方法、代码实现

weixin_67907028的博客 1万+

okhttp源码解析

OkHttp是一个非常优秀的网络请求框架,已被谷歌加入到Android的源码中。目前比较流行的Retrofit也是默认使用OkHttp的。所以OkHttp的源码是一个不容错过的学习资源,学习源码之前,务必熟练使用这个框架,否则就是跟自己过不去。 use -> running source code -> reading & learning the source code. 1、初识

json_it的博客 2万+

【系统架构设计师-2026上半年真题】综合知识-参考答案及详解(75题完全回忆版)

【系统架构设计师-2026上半年真题】综合知识-参考答案及详解(75题完全回忆版)

数据知道的博客 3100

使用 PLS 回归进行近红外光谱的异常值检测

在光谱数据中,并非每个数据点都是有效的,因此,在构建模型时找到与大部分数据不符合的数据点是一种必要的操作。这些数据我们称之为。在这篇文章中,我们将使用PLS回归进行红外光谱数据的异常值检测。

qq_44204759的博客 1422

OKHttp详解

okhttp

liuqinhou的博客 1572

华为Ascend_toolkit在x86ubuntu安装失败报错。[WARNING] driver package is not installed. If you install in docker

这个报错发生在交叉编译配置Ascend_toolkit环境时,安装Ascend_toolkit安装包的时候发生。[Y/N]Y。

anananajiushiwo的博客 1018

OkHttp网络请求流程小结

OkHttp网络请求流程小结 文章目录OkHttp网络请求流程小结前言简单使用源码分析创建Call对象并加入线程池处理通过拦截器发送请求缓存策略HTTP的缓存OkHttp的缓存策略失败重连请求流程图参考资料 前言 本文基于OkHttp 4.7.2,下面的源码都是kotlin,我看了看OkHttp的github,发现最新4.8.0版本kotlin和java五五开,所以还不会kotlin的Android程序猿还不赶快学起来~ 简单使用 OkHttpClient client = new OkHttpClient

qq_43935080的博客 748

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Android Okhttp源码解析流程

okhttp源码解析流程 仅供参考 目前Android网络开发框架已经离不开okhttp,至少我的所有项目基本上都使用的是okhttp。 所以我们需要知其然,更需要知其所以然,今天就开始进行okhttp的源码进行解析。 我使用的library的版本是3.12.1版本的 implementation 'com.squareup.okhttp3:okhttp:3.12.1' 下面是一个正常的使用 OkHttpClient client = new OkHttpClient();

qq_16899301的博客 3257

蓝牙模块HM-10手册

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

OkHttp3

快速了解okhttp的请求过程

weixin_72010379的博客 673

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

OkHttp探索

OkHttp的探索

qq_36639105的博客 972

OKHttp使用详解

在执行call.excute()的时候,调用到realcall类里的excute方法,这个是同步方法,在方法的第一行就加了锁,判断executed标记,如果是true就抛出异常,保证一个请求只被执行一次。先参考现有的框架,找一个比较合适的框架作为启动点,比如说,基于上面讲到的okhttp的优点,选择okhttp的源码进行阅读,并且将主线的流程抽取出,为什么这么做,因为okhttp里面虽然涉及到了很多的内容,但是我们用到的内容并不是特别多;跟他的名字一样,就是做重试工作还有一些连接跟踪工作。

chinaherolts2008的博客 2547

OkHttp(一) — OkHttp 调用流程分析

OKHttp 调用流程分析一、概述二、三、四、 一、概述 二、 三、 四、

Elson的博客 1039

OkHttp流程之Dispatcher

OkHttp的基本流程 android 开发大多用过Okhttp, 在使用过程中,大多也是同步异步两种方式。一般使用方式如下(基于3.14.2版本): public static final MediaType JSON = MediaType.get("application/json; charset=utf-8"); OkHttpClient client = new OkHttp...

alvinhuai的专栏 1471

Android okhttp源码调用流程分析

okhttp 是一套专门为 JVM、Android 设计的 HTTP 客户端,支持同步阻塞调用和带有回调的异步调用,可以非常简单的在 Android 项目中实现网络请求。那么 okhttp 到底是如何做到异步请求?如何实现 HTTP 协议的?本文将通过简单案例对 okhttp 的主要源码进行解读。

孙先森的博客 612
上一篇: 我理解的Handler内部流程
下一篇: Android Studio通过无线的方式连接手机调试
ForMuHan
博客等级 码龄10年 6粉丝 51原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值