一行代码实现Okhttp,Retrofit,Glide下载上传进度监听

OkHttp上传文件并带进度条 android OkHttp上传文件并带进度条 立即下载

原文地址: http://www.jianshu.com/p/5832c776621f

前言

发表上篇文章 我一行代码都不写实现Toolbar!你却还在封装BaseActivity? 已是一个月前的事情,当时有人说我是标题党,也有人不认可我的内容,但是这也不并不妨碍我,两天夺得掘金当周周榜第一,并被 鸿洋公众号 转载,累计阅读量超过 3万

上篇文章的研究成果让 MVPArms 具备了 监听整个 App 所有 Activity 以及 Fragment 的生命周期(包括三方库),并可向其生命周期内插入代码 的功能,这次我又拿着最近的另一项研究成果向大家汇报,当然同样也是 MVPArms 上的新增功能

Github : 你的 Star 是我坚持的动力 ✊

gif

罗列需求

上传下载是大多数 APP 必备的功能,显示进度条也是提高用户体验的重要一环,当然作为 可配置化集成框架 MVPArms 的作者,我想再次提高开发者的使用体验以及开发效率,那我就必须提供一套解决方案

于是我打开 Github 简单的搜了一圈与 Retrofit , Okhttp , Glide 有关的进度监听库,库到是不少,但是都没有达到我想要的需求,于是我卷起衣袖,准备撸一个,当然,开撸之前要先简单梳理下自己的需求

  1. 这个库一定要支持多个平台,Okhttp , Retrofit , Glide 这三个必须同时支持
  2. 虽然支持这三个库,但是库里面并不能包含这三个库,让用户自己去引入,减小库的体积
  3. 使用一定要简单!!!,最好能一行代码搞定
  4. 侵入性低,并不需要改之前写好的网络请求代码,引入与不引入这个库,对之前的代码都不能有任何影响
  5. 低耦合,用户做网络请求的代码,一定不能和进度接收端的代码有太多关联
  6. 在 App 的任何位置都能接受到某个网络请求的 进度信息
  7. 不仅仅需要满足,一个数据源对应一个进度接收端的一对一关系,还需要满足一个数据源对应多个进度接收端的,一对多关系,这样就可以同步更新多个不同位置的进度条
  8. 默认运行在主线程,让使用者少去切换线程的烦恼

需求分析及调研

爽一下子,写出了这么多需求,当产品经理就是一个字爽!

仔细一看这8个需求,瞬间懵逼了,妹的这不是坑自己吗?除了最后一项,我知道可以用 Handler 来实现,其他完全没思路啊,得了,作为一个优质男青年我得知难而进啊,先从第一个需求开始分析吧!

需求 1 (多平台支持)

写之前翻了下 Google 发现,Okhttp 实现上传下载进度监听,并不困难,只用重写 RequestBody 和 ResponseBody ,并配合 Interceptor 将每个请求原有的 RequestBody 和 ResponseBody 替换,就可以实现,都是模版代码,复制粘贴就可以了,而 Retrofit 底层使用的是 Okhttp,那就也可以同样实现进度监听

但是 Glide怎么实现进度监听呢? 我的第一反应就是既然 Retrofit 使用 Okhttp 请求网络就可以非常容易的实现,那将 Glide 的底层请求框架换成 Okhttp 也可以实现咯,作为一个如此牛逼的库,肯定有扩展的方式,于是马上去翻 Glide 的源码,印证了自己的想法,发现 Glide 底层是使用的 HttpConenction 去请求网络,并且这个类时可以被替换的,赶快 Google 了下

compile 'com.github.bumptech.glide:okhttp3-integration:1.4.0@aar'

ok,找到解决方案,可用上面提供的类,将底层请求框架替换为 Okhttp ,这个框架最核心的地方已经找到实现方式,主要是通过 Okhttp 实现,如同吃了定心丸,瞬间舒坦

需求 2 (减小体积)

这个需求 Google 了下,也非常简单,用 provided 引入依赖框架,打包时引入的框架就不会包含进去

需求 3 (一行代码实现)

对于这种对外 Api 设计上的需求,我们应该把主体功能实现了,再慢慢优化到想达到的目标所以先分析下面的需求

需求 4 (侵入性低)

因为需求 1 已经提到,实现上传和下载进度监听的关键就是,在 Interceptor 中将每个请求原有的 RequestBody 和 ResponseBody 替换成重写后的

如何识别需要监听进度的请求?

替换是简单,但是不是每个请求都需要监听上传和下载进度,不可能每个请求都替换啊,开始我想到的是给需要监听进度的请求生成个标记,然后在 Interceptor 中解析到这个标记,就说明这个请求需要监听上传或下载进度,然后就开始替换之

于是我想到最简单的方式就是在请求的时候加一个自定义的 Header ,这样就不用再定义其他的类, Interceptor 遍历所有 Header 发现有这个自定义 Header ,就可以替换

但是这样并没有解决需求 4,因为这样让用户比平时请求时多了个操作,如果想让之前的代码具有进度监听功能,就要一个个挨着改,增加了劳动量,而且这个操作是针对于我这个库而产生的,当用户并不想使用这个库的时候,会牵扯到修改之前的代码,这样还增加了侵入性

Url 作为标记

一个念头一闪而过,还要什么标记, Url 是唯一的, 不就可以作为标记吗!!!

需求 5 (低耦合) ,需求 6 (任何位置都可接收),以及 需求 7 (一对多)

借用 EventBus 思想

为什么把这三个需求放在一起呢,因为这三个需求让我想到了 EventBus ,多个观察者使用同一个标记将自己注册进一个容器,被观察者使用这个标记 Post 一个事件,然后从这个容器中拿出所有使用这个标记注册过的观察者,挨个通知,这样既解耦,并且只要知道这个标记,在 App 任何位置都可以监听,也支持一对多

加上需求 4,中提到的使用 Url 作为标记,那我就可以做到之前请求的代码一个也不用改,只用写接收端的代码即可实现以上的需求

构思 Api

既然谈到 EventBus ,那我就用 EventBus 的 Api 来设计,用户只用一行代码,传入一个 标记 和一个 事件 即可实现上传和下载进度监听,没错 标记 就是 Url , 事件 就是用于获取进度信息的 监听器,这样也就满足了 需求 3 的一行代码实现的需求

Like this

ProgressManager.post(标记,事件);

用户调用这一行代码后,我会将 Url 作为 Key,监听器 作为 value 放入一个全局唯一的 Map 中

等等?说好一对多的呢?所以这个 value 必须是 List< 监听器 > ,这样就满足了一对多的条件了

内部如何通知监听器?

我们把所有需要监听的 Url 的 监听器 都注册进了这个容器,那我们什么时候该去通知 监听器 进度信息呢,当然是在 RequestBody 和 ResponseBody 中开始写入或读取二进制流的时候,因为只有他们第一时间知道,读取和写入的时间,现在只需要把对应 Url 的所有 监听器 放入他的 Body 中就可以了

因为 需求 4 中提到,我们并不知道哪些请求是需要监听上传或下载进度,哪些是不需要的,但是现在我们就可以通过 Url 来辨别,因为我们可以在 Interceptor 中拿到 Request 的 Url

之前我们已经将 Url 作为 Key 注册进了容器,如果容器里面 Contain 这个 Url 那就是说明这个请求,是需要监听上传或下载进度的,那我们就给他替换成重写后的 Body 并将监听器传入,重写后的 Body 在发生二进制流的 读取 或 写入 时不断的遍历这个 Url 的所有 监听器,调用 监听器 的监听方法,并传入进度信息,就可以执行使用者的更新逻辑,这就大功告成了

需求 8 (主线程执行)

这个很简单,使用 Handler.post(Runnable) 在 Runnable 中调用 监听器 的方法就可以了

框架细节优化

无需手动注销

大家都知道 EventBus 注册观察者后,在不需要接受事件时,需要手动注销,但是应用到我这个库中,事件的接受可能不需要这么严谨,所以为了免去使用者多余的步骤,我就是使用 WeakHashMap 代替之前的 Map 容器,这个 WeakHashMap 会在 Java虚拟机 回收内存时,找到没被使用的 Key,将此条目整个移除,所以不需要手动 remove()

加锁

在上面提到用户只需要一行代码,将 Url 和 监听器 加入容器,但是这行代码,可能是在不同线程中被调用的,而且这行代码内的一些逻辑在多线程中是不安全的,所有这时我需要加入线程锁,这个对于三方库很重要,因为你无法预知一些用户的操作

向使用者抛出清晰的错误

因为我在 需求 2 中已经提到,此库只会用 provided 引入 Okhttp ,所以 Okhttp 是不会被打进 arr 包里的,所以如果使用者在自己的项目中没有引入 Okhttp 是会报 NoClassDefFoundError 这个错误的,但是这个错误会让使用者不知道真实的出错原因,让使用者误以为是这个库的导致的,所以我会在库初始化的时候, Class.forName(“okhttp3.OkHttpClient”); 如果找不到 Okhttp 的这个类,说明使用者没有引入 Okhttp ,然后我会抛出一个解释非常清晰的错误

提高性能

因为上面提到过我会在 Body ,开始读取或写入二进制流时,不断的遍历所有监听器并调用它的监听方法,来达到一对多的同步更新

但是这样 监听器 达到一定数量就会出现性能问题,并且在遍历时,搞不好使用者也会,不断的添加新的监听器,在遍历时改变容器的长度是容易发生错误的

所以我在将 List 传入 Body 时,将这个 List.toArray() ,数组分配的是连续的内存区域并且长度是固定的,所以索引效率占有优势,则使用数组来遍历,由于数组长度是固定的,所以也不会出现遍历时长度变化的问题

区分同一个Url的多个进度

因为 App 用户可能在前一个进度还没上传或下载完的情况下,继续使用同一个 Url 开始新的请求,如果框架使用者在上层不去做去除重复点击的操作,那同一个 Url 就会同时存在多个正在执行的进度更新,这时就需要有标识符来区分到底是哪个进度信息(这个 Url 的所有正在执行的进度更新都会调用之前以这个 Url 注册过的监听器),所以我在 Body ,创建时会将 System.currentTimeMillis() 作为唯一 ID ,保存起来,每次将进度信息和 Id 一起传给使用者

总结

其实这个库本来就比较简单,实现的核心方式在很多地方都是能复制粘贴到的,但经过我这么一封装还是要比之前的方式,简单优雅不少,而写这篇文章的目也是想分享下,如何分析需求,以及如何封装优化一个小型的库,当然平时也要多阅读源码,不断积累和借鉴优秀的思想在创作时灵感才会源源不断,比如我这个库就是借鉴的 EventBus 的思想,在写代码时要敢于想敢于尝试较于之前不同的新思想,才会不断进步

Github : 具体实现还得看源码不是? 记得给 Star ✊ 感谢!


Hello 我叫Jessyan,如果您喜欢我的文章,可以在以下平台关注我

– The end

使用nvm离线安装、管理node多版本以及配置环境变量(亲测) 阅读详情

相关推荐

告别抖动与滞后:深入博能传动伺服DSC功能,用105报文提升多轴同步性能

本文深入解析博能传动伺服DSC功能如何通过105报文实现多轴同步性能提升,有效解决工业自动化中的抖动与滞后问题。详细介绍了DSC技术原理、105报文实现机制及多轴同步工程实践,帮助工程师优化伺服系统性能,实现绝对齿轮同步。

weixin_30394981的博客 184

Android图片加载框架最全解析(四),玩转Glide的回调与监听

大家好,今天我们继续学习Glide。在上一篇文章当中,我带着大家一起深入探究了Glide的缓存机制,我们不光掌握了Glide缓存的使用方法,还通过源码分析对缓存的工作原理进行了了解。今天是这个Glide系列的第四篇文章,我们又要选取一个新的功能模块开始学习了,那么就来研究一下Glide的回调和监听功能吧。今天的学习模式仍然是以基本用法和源码分析相结合的方式来进行的

郭霖的专栏 6万+

AI Agent生产环境压测指南:并发、延迟与资源瓶颈定位

去年我接触了不下10个AI Agent上线翻车的案例:有做智能客服的公司双11当天流量暴涨3倍,Agent服务直接雪崩,用户咨询全超时,损失超200万订单;有做企业内部RAG Agent的团队,上线后100人同时查询就把向量库打挂,还连累了其他业务的数据库;还有做多智能体系统的团队,压测只测了单请求性能,上线后多Agent交互超时率高达30%。

软件工程实践的博客 171

retrofit2+okhttp3图片上传及进度监听

1、使用jar包 由于retrofit2与1的写法有很大的变化,并且对okhttp存在着依赖。所以需要确定选择使用方向,以免陷入不必要的坑中。 本篇讲采用retrofit2 + okhttp3做结合使用。在导包过程中本人也遇到了一些不兼容的麻烦,再此做记录。 retrofit-2.1.0.jar、okhttp-3.4.1.jar、okio-1.6.0.jar、converter-gson-2

shizhesx的博客 4304

物联网定位技术|实验报告|实验一 Wi-Fi指纹定位

全球定位系统是迄今为止应用最为成功的地位系统,具备高精度的定位能力,但在室内和高楼密布的城区等信号遮挡严重的密集环境中,由于接受机捕获不到足够强度的卫星信号,GPS的定位质量难以保证甚至无法完成定位,使其可用性受到严重制约。由于室内环境下都普及了WiFi,因此利用WiFi进行定位无需额外部署硬件设备,是一个非常节省成本的方法。

m0_57656758的博客 3356

dify工作流的原理

摘要: Dify 工作流是一个基于有向无环图(DAG)的智能任务编排系统,支持多节点(如LLM调用、API工具、条件分支等)的可视化拖拽与流程编排。其核心原理包括执行引擎(解析DAG并管理节点依赖)、上下文变量传递(类Jinja模板的变量引用机制)和状态持久化(存储执行日志与中间结果)。工作流通过事件驱动执行,支持异步任务调度,并与RAG知识库、LLM服务等模块深度集成,最终可发布为API或对话应用。技术栈基于Python(FastAPI+Celery)和PostgreSQL,实现低代码化的AI应用开发。

nbspzs的专栏 2187

ESP32-C3 USB蓝牙Dongle:小尺寸高并发BLE接入方案

BLE(低功耗蓝牙)作为物联网设备主流无线通信协议,其稳定接入能力直接影响智能家居系统可用性。传统USB蓝牙适配器受限于芯片架构(如RTL8761B、nRF52840),普遍存在连接数瓶颈、iOS后台断连、广播丢包率高等问题。本文聚焦ESP32-C3单芯片方案,依托其原生USB 2.0 Full-Speed PHY与内置BLE 5.0 Controller,在19mm超小尺寸内实现USB Device + BLE Host + 协议栈全集成,突破Linux BlueZ依赖,支持20+设备高并发扫描与毫秒级响

weixin_34239592的博客 317

YOLOv13涨点改进 | 独家创新、Neck特征融合改进篇 | TGRS 2024 | 引入 EFC增强跨层特征相关创新点,含MSEF(多尺度有效融合模块)二次创新模块,助力遥感目标检测涨点

本文提出EFC(增强跨层特征相关)模块改进YOLOv13模型,显著提升小目标检测性能。EFC通过分组特征聚焦(GFF)和多层特征重建(MFR)增强特征融合效率,在小目标检测任务中平均精度(mAP)提升1.7%,同时减少模型计算量。实验验证EFC在VisDrone等数据集上的有效性,改进后的模型能更好地保留小目标细节信息。还提出二次创新模块MSEF,集成通道和位置注意力机制,进一步优化特征表达。文章详细介绍了模块配置方法和yaml文件修改步骤,为小目标检测任务提供了实用的改进方案。

Ai缝合怪、助力小伙伴高效发论文 325

ProgressManager终极指南:一行代码监听OkHttp/Retrofit/Glide网络进度的神奇框架

ProgressManager是一款专为Android开发者打造的网络进度监听框架,它能帮助你轻松实现对OkHttp、Retrofit和Glide等主流网络库的上传下载进度监听功能。通过简单的集成步骤,开发者可以快速为应用添加专业的进度显示功能,提升用户体验。 ## 为什么选择ProgressManager? 在移动应用开发中,网络请求的进度反馈是提升用户体验的关键因素。无论是图片加载、文件下

gitblog_01182的博客 660

基于Cesium实现,动态水面+大坝排水动画

一、绘制面状水域,使用水波纹理,进行渲染,水体透明,可以看到底色。三、使用粒子系统,将喷泉改变方向,加上重力设置,实现排水动画。二、绘制线状三维体,用作模拟大坝拦截效果。四、最后,模拟水位上升,进行淹没分析,

一醉千秋的专栏 1420

pyecharts在jupyter notebook中不能够渲染图表问题。

在使用jupyter notebook中使用pyecharts绘制可视化图表的时候,发现图表不能渲染到页面中,生成的html是没问题的,本文主要解决在jupyter notebook中不能渲染这个问题。

猿小白的博客 1167

开发者必看:MiniCPM-V-4.6-Thinking-BNB API服务搭建与优化指南

MiniCPM-V-4.6-Thinking-BNB 是 OpenBMB 开源社区推出的轻量级多模态模型 API 服务解决方案,基于 bitsandbytes 技术实现 4 位量化,在保持高效图像与视频理解能力的同时,显著降低资源占用,特别适合开发者快速部署高性能 AI 服务。 ## 🌟 为什么选择 MiniCPM-V-4.6-Thinking-BNB? 作为 MiniCPM-V 4.6 的

gitblog_01204的博客 969

Allegro172版本如何在联机模式下使用skill文件操作指导

注意:如果下次重新开启Symphony模式的时候可能导致symphony_skill中的文件内容被清空,所以最好将自己常用的skill文件都写到symphony_skill.txt中去,然后做好备份,需要的时候,在开启软件后把文件放到env目录中去。在用Allegeo172版本进行PCB设计的时候,有时会用到Symphony模式进行多人实时在线协同设计,如下图。这个模式设计起来可以提升设计速度,但是也有一个缺陷,就是不能使用skill文件。如下图,当调用skill的时候就会出现如下报错。

weixin_54787054的博客 1586

AAAAAAAAAAAAAAA

深入理解Android之AOP一行代码实现Okhttp,Retrofit,Glide下载上传进度监听Java基础之—反射(非常重要)Android 网络框架_常用的网络框架Android 冷兵器 之 tools

随风的博客 453

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

Llama-2-13b-chat-ms vs 其他开源模型:为什么它是对话场景的最佳选择

Llama-2-13b-chat-ms 是 Meta 推出的 Llama 2 系列大语言模型中 130 亿参数的对话优化版本,专为对话场景设计,在开源模型中表现出色。它采用优化的 transformer 架构,通过监督微调(SFT)和人类反馈强化学习(RLHF)来对齐人类偏好,实现了在对话场景下的卓越性能。 ## 对话场景下的核心优势 ### 1. 出色的对话能力与安全性平衡 Llama-2-

gitblog_00524的博客 552

WINCC7.3破解文件

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

推荐使用ProgressManager:优雅地实现全局网络进度监听

在网络传输越来越频繁的今天,无论是下载文件还是上传数据,用户都希望实时了解进度以便做出相应操作。这就催生了**ProgressManager**——一个轻量级且强大的Android框架,它能帮助开发者轻松地监听应用中所有网络链接的下载与上传进度,甚至包括Glide的图片加载进度。 ## 项目介绍 **ProgressManager** 是由 JessYan 创建的开源项目,它通过简单的接口设计...

gitblog_00073的博客 499

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

3 分钟接入 REA:新手完整逆向实战,如何把闭源应用的搜索功能复刻成有证据的代码

REA 是面向 AI 智能体的开源逆向工程工具:一条 `npx rea-agents setup` 就能让你的 Agent 连上 Hopper、Ghidra 或 IDA 读懂闭源二进制,同一套 CLI 命令也能在终端里直接跑。本文以 macOS Notes 的离线搜索框为对象,从一句提问开始,走完五步反编译取证,到一段可本地运行的复刻实现。"没有加载圈就立刻返回"的功能,到底能不能被复刻?你的结论

gitblog_00231的博客 324
上一篇: 我一行代码都不写实现Toolbar!你却还在封装BaseActivity?
下一篇: !!!解决Retrofit多BaseUrl及运行时动态改变BaseUrl?
JessYanCoding
博客等级 码龄10年 63粉丝 15原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值