当前位置: 首页 > news >正文

Android OkHttp 源码浅析一

演进之路:原生Android框架不好用 ---- HttpUrlConnect   和 Apache HTTPClient  

第一版  底层使用HTTPURLConnect  

第二版 Square构建 从Android4.4开始

基本使用:

 val okhttp = OkHttpClient()val request = Request.Builder().url("http://www.baidu.com").build()okhttp.newCall(request).enqueue(object : okhttp3.Callback{override fun onFailure(call: okhttp3.Call, e: IOException) {Log.e("--->",e.message!!)}override fun onResponse(call: okhttp3.Call, response: okhttp3.Response) {Log.e("--->",response.body!!.string())}})//enqueue Call接口定义的抽象方法
//newCall RealCall创建出 有三个参数 1 okhttpclient  2.quest originnalRequest 3. forWebSocket //Booleaan
//WebSocket 是通过http创建连接
//

 override fun enqueue(responseCallback: Callback) {check(executed.compareAndSet(false, true)) { "Already Executed" }callStart()
//dispatcher 用来做线程调度 管理 Executor 线程池
//MaxRequests  = 64 最大64个线程  
//MaxRequestPerHost = 5 最多同一主机线程  5client.dispatcher.enqueue(AsyncCall(responseCallback))}override fun isExecuted(): Boolean = executed.get()private fun callStart() {
//跟踪错误分析和记录this.callStackTrace = Platform.get().getStackTraceForCloseable("response.body().close()")
//监听一系列事件 连接建立 断开连接 报文 head body 发送等eventListener.callStart(this)}
@get:Synchronized var maxRequests = 64 最多连接数量 64
@get:Synchronized var maxRequestsPerHost = 5 同一主机 5
internal fun enqueue(call: AsyncCall) {synchronized(this) {readyAsyncCalls.add(call)// Mutate the AsyncCall so that it shares the AtomicInteger of an existing running call to// the same host.if (!call.call.forWebSocket) {val existingCall = findExistingCallWithHost(call.host)if (existingCall != null) call.reuseCallsPerHostFrom(existingCall)}}promoteAndExecute()}

同步方法,Deque 双向队列

AsyncCall 共享变量 记录连接数等
if (!call.call.forWebSocket) {//记录数量val existingCall = findExistingCallWithHost(call.host)if (existingCall != null) call.reuseCallsPerHostFrom(existingCall)
}

private fun promoteAndExecute(): Boolean {this.assertThreadDoesntHoldLock()val executableCalls = mutableListOf<AsyncCall>()val isRunning: Booleansynchronized(this) {val i = readyAsyncCalls.iterator()while (i.hasNext()) {val asyncCall = i.next()if (runningAsyncCalls.size >= this.maxRequests) break // Max capacity.if (asyncCall.callsPerHost.get() >= this.maxRequestsPerHost) continue // Host max capacity.i.remove()asyncCall.callsPerHost.incrementAndGet()executableCalls.add(asyncCall)runningAsyncCalls.add(asyncCall)}isRunning = runningCallsCount() > 0}for (i in 0 until executableCalls.size) {val asyncCall = executableCalls[i]asyncCall.executeOn(executorService)}return isRunning}
promoteAndExecute 准备执行函数
readyAsyncCalls 没有执行过的请求 不会超出限制 64 or 5

executableCalls 添加到calls 然后取出遍历 执行 executeOn

val i = readyAsyncCalls.iterator() 遍历被执行的call
if (runningAsyncCalls.size >= this.maxRequests) break // Max capacity.
if (asyncCall.callsPerHost.get() >= this.maxRequestsPerHost) continue // Host max capacity. 超出连接限制的数量 终止请求
i.remove() //移除当前请求
asyncCall.callsPerHost.incrementAndGet()
executableCalls.add(asyncCall) 
runningAsyncCalls.add(asyncCall)

runningAsyncCalls 正在执行的Call

   for (i in 0 until executableCalls.size) {
      val asyncCall = executableCalls[i]

遍历准备执行的call  然后调用executeOn
      asyncCall.executeOn(executorService)
    }

Okhttp enqueue ----> newCall ---> RealCall enqueue ------>  执行 dispatcher . enqueue ---->  添加到readyAsyncCalls ----> promoteAndExecute ---executeOn 执行

  fun executeOn(executorService: ExecutorService) {client.dispatcher.assertThreadDoesntHoldLock()var success = falsetry {executorService.execute(this)success = true} catch (e: RejectedExecutionException) {val ioException = InterruptedIOException("executor rejected")ioException.initCause(e)noMoreExchanges(ioException)responseCallback.onFailure(this@RealCall, ioException)} finally {if (!success) {client.dispatcher.finished(this) // This call is no longer running!}}}

executorService dispatcher 内部类管理的对象 线程调度 参数是runnable

        executorService.execute(this) 线程切换到后台线程 Async 实现了Runnable

线程调度

 override fun run() {threadName("OkHttp ${redactedUrl()}") {var signalledCallback = falsetimeout.enter()try {val response = getResponseWithInterceptorChain()signalledCallback = trueresponseCallback.onResponse(this@RealCall, response)} catch (e: IOException) {if (signalledCallback) {// Do not signal the callback twice!Platform.get().log("Callback failure for ${toLoggableString()}", Platform.INFO, e)} else {responseCallback.onFailure(this@RealCall, e)}} catch (t: Throwable) {cancel()if (!signalledCallback) {val canceledException = IOException("canceled due to $t")canceledException.addSuppressed(t)responseCallback.onFailure(this@RealCall, canceledException)}throw t} finally {client.dispatcher.finished(this)}}}

    val response = getResponseWithInterceptorChain() 获取相应 

getResponseWithInterceptorChain 请求数据的方法封装

responseCallback 代码里声明传入的Callback

相关文章:

Android OkHttp 源码浅析一

演进之路:原生Android框架不好用 ---- HttpUrlConnect 和 Apache HTTPClient 第一版 底层使用HTTPURLConnect 第二版 Square构建 从Android4.4开始 基本使用: val okhttp OkHttpClient()val request Request.Builder().url("http://www.baidu.com").buil…...

【Redis】——Redis基础的数据结构以及应用场景

什么是redis数据库 Redis 是一种基于内存的数据库&#xff0c;对数据的读写操作都是在内存中完成&#xff0c;因此读写速度非常快&#xff0c;常用于缓存&#xff0c;消息队列、分布式锁等场景。&#xff0c;Redis 还支持 事务 、持久化、Lua 脚本、多种集群方案&#xff08;主…...

SpringBoot+WebSocket搭建多人在线聊天环境

一、WebSocket是什么&#xff1f; WebSocket是在单个TCP连接上进行全双工通信的协议&#xff0c;可以在服务器和客户端之间建立双向通信通道。 WebSocket 首先与服务器建立常规 HTTP 连接&#xff0c;然后通过发送Upgrade标头将其升级为双向 WebSocket 连接。 WebSocket使得…...

推荐适用于不同规模企业的会计软件:选择最适合您企业的解决方案

高效的会计软件不仅可以协助企业进行财务管理&#xff0c;做出科学的财务决策&#xff0c;还可以对企业数字化转型提供助力。不同规模的企业需要根据其特定需求选择适合的会计软件。那么有什么适合不同规模企业的会计软件推荐吗&#xff1f; 小型企业的选择 对于小型企业而言&…...

Apache Zookeeper架构和选举机制

ZooKeeper是一个开源的分布式协调服务,旨在解决分布式系统中的一致性、配置管理、领导者选举等问题。它由Apache软件基金会维护,是Hadoop生态系统的一部分,被广泛用于构建高可用、可靠和具有一致性的分布式应用程序和服务。 ZooKeeper提供了一个层次化的命名空间,类似于文…...

车联网TCU USB的配置和使用

1 usb_composition命令 # cat /sbin/usb/target # cd /sys/class/android_usb/android0 # cat functions console shows that QCOM’s default configuration Usage: usb_composition [Pid] [HSIC] [PERSISTENT] [IMMEDIATE] [FROM_ADBD] usb_composition 9025 n y y Then this…...

Linux系统USB摄像头测试程序(三)_视频预览

这是在linux上usb摄像头视频预览程序&#xff0c;此程序用到了ffmpeg、sdl2、gtk3组件&#xff0c;程序编译之前应先安装他们。 #include <sys/ioctl.h> #include <sys/stat.h> #include <sys/types.h> #include <fcntl.h> #include <zconf.h> …...

目标检测任务数据集的数据增强中,图像水平翻转和xml标注文件坐标调整

需求&#xff1a; 数据集的数据增强中&#xff0c;有时需要用到图像水平翻转的操作&#xff0c;图像水平翻转后&#xff0c;对应的xml标注文件也需要做坐标的调整。 解决方法&#xff1a; 使用pythonopencvimport xml.etree.ElementTree对图像水平翻转和xml标注…...

系统架构的演变

随着互联网的发展&#xff0c;网站应用的规模不断扩大&#xff0c;常规的应用架构已无法应对&#xff0c;分布式服务架构以及微服务架构势在必行&#xff0c;必需一个治理系统确保架构有条不紊的演进。 单体应用架构 Web应用程序发展的早期&#xff0c;大部分web工程(包含前端…...

IDC发布《亚太决策支持型分析数据平台评估》报告,亚马逊云科技位列“领导者”类别

日前&#xff0c;领先的IT市场研究和咨询公司IDC发布《2023年亚太地区&#xff08;不含日本&#xff09;决策支持型分析数据平台供应商评估》1报告&#xff0c;亚马逊云科技位列“领导者”类别。IDC认为&#xff0c;亚马逊云科技在解决方案的协同性、敏捷性、完整性、及时性、经…...

C#之OpenFileDialog创建和管理文件选择对话框

OpenFileDialog 是用于图形用户界面&#xff08;GUI&#xff09;编程的一个类&#xff0c;它用于显示一个对话框&#xff0c;允许用户选择要打开的文件。在需要用户加载或打开文件的应用程序中&#xff08;如文本编辑器、图像查看器或文档处理器&#xff09;&#xff0c;这是一…...

Java中使用MongoTemplate 简单操作MongoDB

Autowired private MongoTemplate mongoTemplate; User&#xff1a;封装的对象 插入&#xff1a;mongoTemplate.insert(user); 根据id查询&#xff1a;mongoTemplate.findById(id, User.class); 查询所有&#xff1a;mongoTemplate.findAll(User.class); 条件查询&#…...

[Mac软件]Pixelmator Pro 3.3.12 专业图像编辑中文版

Pixelmator Pro是专为Mac设计的功能强大&#xff0c;美观且易于使用的图像编辑器。借助广泛的专业级无损图像编辑工具&#xff0c;Pixelmator Pro可使您发挥出最佳的照片效果&#xff0c;创建华丽的构图和设计&#xff0c;绘制&#xff0c;绘画&#xff0c;应用令人惊叹的效果&…...

吴恩达 GPT Prompting 课程

Prompting Guidelines 目录 Guidelines for PromptingPrompting Principles Principle 1: Write clear and specific instructions1.1: Use delimiters to clearly indicate distinct parts of the input1.2: Ask for a structured output1.3: Ask the model to check whether …...

gpt3.5写MATLAB代码剪辑视频,使之保留画面ROI区域

% 输入和输出文件名 inputVideoFile input_video.mp4; outputVideoFile output_video.mp4;% 创建 VideoReader 和 VideoWriter 对象 videoReader VideoReader(inputVideoFile); outputVideo VideoWriter(outputVideoFile, MPEG-4); outputVideo.FrameRate videoReader.Fra…...

设计模式二十一:状态模式(State Pattern)

一个对象的内部状态发生变化时&#xff0c;允许对象改变其行为。这种模式使得一个对象看起来好像在运行时改变了它的类&#xff0c;主要目的是将状态的行为从主要对象中分离出来&#xff0c;使得主要对象不必包含所有状态的逻辑&#xff0c;而是将每个状态的行为封装在独立的类…...

【校招VIP】产品思维能力之产品设计

考点介绍&#xff1a; 对于产品经理来说最重要的就是产品思维&#xff0c;而拥有一个好的产品思维需要做到以下三点&#xff1a; 1、把握关键点的能力 2、出方案&#xff0c;协调资源&#xff0c;说服团队把资源倾斜到关键点上的能力 3、评估关键点进展程度的能力 『产品思维能…...

微信小程序卡片横向滚动竖图

滚动并不是使用swiper&#xff0c;该方式使用的是scroll-view实现 Swiper局限性太多了&#xff0c;对竖图并不合适 从左往右滚动图片示例 wxml代码&#xff1a; <view class"img-x" style"margin-top: 10px;"><view style"margin: 20rpx;…...

SpringBoot项目(支付宝整合)——springboot整合支付宝沙箱支付 从极简实现到IOC改进

目录 引出git代码仓库准备工作支付宝沙箱api内网穿透 [natapp.cn](https://natapp.cn/#download) springboot整合—极简实现版1.导包配置文件2.controller层代码3.进行支付流程4.支付成功回调 依赖注入的改进1.整体结构2.pom.xml文件依赖3.配置文件4.配置类&#xff0c;依赖注入…...

【AIGC】一款离线版的AI智能换脸工具V2.0分享(支持图片、视频、直播)

随着人工智能技术的爆发&#xff0c;AI不再局限于大语言模型&#xff0c;在图片处理方面也有非常大的进步&#xff0c;其中AI换脸也是大家一直比较感兴趣的&#xff0c;但这个技术的应用一直有很大的争议。 今天给大家分享一个开源你的AI换脸工具2.0&#xff0c;只需要一张所需…...

Solidity 智能合约入门:从 0 到 1 编写第一个区块链合约

一、什么是 Solidity&#xff1f; Solidity 是一门面向以太坊虚拟机&#xff08;EVM&#xff09;、静态类型的高级编程语言&#xff0c;专门用于编写区块链上的智能合约。 简单来说&#xff1a; 智能合约 运行在区块链上的自动执行代码&#xff08;无需第三方&#xff0c;代…...

基于 MATLAB 的非线性优化算法实现:BFGS + Armijo 线搜索

基于matlab的非线性优化算法实现 通过梯度下降法&#xff08;具体实现为 BFGS 方法&#xff09;&#xff0c;并结合 Armijo 线搜索方法&#xff0c;对一个多项式目标函数进行优化&#xff0c;找到其最优解。 开发语言&#xff1a;matlab非线性优化问题在科学计算和工程应用中非…...

汽车电子测试人的 Prompt 工程

专栏&#xff1a;《AI 汽车电子测试实战》第 17 篇 作者&#xff1a;一线汽车电子测试工程师 适合人群&#xff1a;所有使用 AI 的测试工程师、想提升 AI 使用效率的测试人员开篇&#xff1a;为什么需要学 Prompt&#xff1f; 这是我上个月在某车企的 AI 培训项目中的真实经历。…...

Realtek RTL8125 2.5GbE网卡驱动技术指南

Realtek RTL8125 2.5GbE网卡驱动技术指南 【免费下载链接】realtek-r8125-dkms A DKMS package for easy use of Realtek r8125 driver, which supports 2.5 GbE. 项目地址: https://gitcode.com/gh_mirrors/re/realtek-r8125-dkms 1. 问题诊断&#xff1a;网络设备识别…...

系统焕新:Win11Debloat工具让Windows性能提升51%的全方位优化方案

系统焕新&#xff1a;Win11Debloat工具让Windows性能提升51%的全方位优化方案 【免费下载链接】Win11Debloat 一个简单的PowerShell脚本&#xff0c;用于从Windows中移除预装的无用软件&#xff0c;禁用遥测&#xff0c;从Windows搜索中移除Bing&#xff0c;以及执行各种其他更…...

深入对比:在Vivado中设计异步复位、同步复位和带使能D触发器的实战差异与选型建议

深入对比&#xff1a;在Vivado中设计异步复位、同步复位和带使能D触发器的实战差异与选型建议 当你在设计一个状态机或数据流水线时&#xff0c;是否曾为选择哪种D触发器而犹豫不决&#xff1f;异步复位、同步复位还是带使能的D触发器&#xff0c;每种设计都有其独特的应用场景…...

百川2-13B-4bits量化实测:OpenClaw长文本处理会丢信息吗?

百川2-13B-4bits量化实测&#xff1a;OpenClaw长文本处理会丢信息吗&#xff1f; 1. 测试背景与动机 最近在尝试用OpenClaw搭建个人自动化工作流时&#xff0c;遇到一个实际问题&#xff1a;当处理长文档&#xff08;比如几十页的PDF或网页文章&#xff09;时&#xff0c;AI助…...

超级AI数字员工源码系统,支持贴牌OEM,独立部署交付

温馨提示&#xff1a;文末有资源获取方式最近“龙虾AI”概念很火&#xff0c;到处都在讨论。但说实话&#xff0c;这类技术对普通用户而言存在明显门槛&#xff0c;部署要代码、配置要工程师、日常运行的Token成本也不低——轻度使用每月100-200元&#xff0c;重度甚至单日上千…...

手把手教你用51单片机实现蓝牙+WiFi双模控制智能小车(附OLED显示速度)

从零构建51单片机智能小车&#xff1a;双模无线控制与速度显示实战指南 引言 想象一下&#xff0c;当你坐在沙发上&#xff0c;用手机就能遥控一台自制的小车在房间里自由穿梭&#xff0c;同时还能实时查看它的行驶速度——这种极客般的体验其实并不遥远。基于51单片机的智能…...

【开发工具】Trae IDE 解决 Windows 下 C 工程无法跳转定义问题

1. 概要 &#x1f44b; 作为 Trae IDE 使用者&#xff0c;在 Windows 环境打开本地 C 工程时&#xff0c;习惯用 Ctrl 鼠标左键 快速跳转函数 / 变量定义却失效&#xff0c;仅能做文本匹配&#xff0c;无法精准定位语义定义。核心原因是 Trae 依赖 LSP&#xff08;语言服务器协…...