Android 大图显示优化方案-加载Gif 自定义解码器
基于Glide做了图片显示的优化,尤其是加载Gif图的优化,原生Glide加载Gif图性能较低。在原生基础上做了自定义解码器的优化,提升Glide性能
Glide加载大图和Gif 尤其是列表存在gif时,会有明显卡顿,cpu和内存占用较高,
Glide的优势 就是有一套图片生命周期的维护,但是加载gif效率比不上android-gif-drawable库,原因就是glide是java层加载的,后者是native层加载的 使用的是giflib库
解决方案:
Glide+giflib
因为giflib是C库,我们调用比较不便,好在Google官方封装好了一个 frameSequence
步骤一:生成so文件
下载好framesequence和giflib包,然后在framesequence目录中创建external目录,并将giflib解码目录复制到该目录下,然后执行ndk-build,最后将生成的so放到jnilibs目录下。
步骤二:创建FrameSequence对象以及FrameSequenceDrawable对象
frameSequence的sample项目中已有了,直接复制过来就可以使用了
步骤三 自定义glide资源解码器
经过以上三步,准备工作已做好,接下来就是要将frameSequence和glide进行结合了。frameSequence负责图片解码,glide负责下载和生命周期维护。想要替换解码部分,就必须了解glide的实现了。glide加载过程分为加载和解码两大步骤,其中加载过程是通过模型加载器(ModelLoader)来实现,而解码过程是通过资源解码器(ResourceDecoder)来实现的,所以我们要做的就是将glide的ResourceDecoder中默认的解码操作替换成frameSequence。
那应该怎么给glide注册一个资源解码器呢?
其实Glide v4 使用 APT(注解处理器) 来生成出一个 API。可以为 Generated API 扩展自定义选项,我们可以继承AppGlideModule,重写registerComponents方法,在里面添加一个gif解码器。注意需要使用@GlideModule进行注解,添加完该注解后在编译时会自动生成一些类。这里将glide.getBitmapPool传递到解码器中是为了bitmap的复用
写好这个类后,我们直接编译一下项目,就会发现glide自动为我们生成了很多的java文件,如下图:
接下来我们再看看核心的解码器需要做什么操作
我们可以看到,这里面首先构造方法接收到了glide注册机传过来的bitmapPool,用在decode方法中进行复用。在handles中返回true代表我们的解码器直接处理了该任务,然后在最核心的decode方法中,我们初始化了一个FrameSequenceDrawable并且返回。这里由于返回值是Resource,所以我们不得不包了一层自定义的Resource子类。
什么是内存抖动?
内存抖动是指频繁的申请内存,然后又回收内存,使得内存使用很不稳定,万一没有回收好就会产生内存泄漏。
什么是内存碎片?
在连续的内存空间中,有一部分内存被使用,另一部分已经被回收,所以导致目前可使用的内存空间不是连续的,而不是连续的将不可以同时一次性拿来使用。比如内存空间是1 2 3 4个格子,其中1和3是正在使用的内存,2和4是空闲内存,此时如果2和4单个的内存空间不够,那么就需要同时申请到2和4,由于2和4的空间不连续,所以就会导致申请失败。其中2和4这2个内存空间就被称为内存碎片,太小的碎片将无法使用,非常影响效率。
有关bitmapPool的复用
这里我贴出谷歌官方的2张图,第一张是复用前,每个图片都分配一个内存空间。第二张是复用后,所有图片复用同一个bitmap空间,减少内存使用。
步骤四 自定义解码器的使用
最后,我们通过调用之前通过APT生成的GlideApp,然后通过as方法传入FSDrawable的方式来调用我们自定义的解码器
是否还能优化一下调用流程?
以上实际的加载优化已经完成,但是我们发现调用的时候需要as方法传入FrameSequenceDrawable,写起来很不方便,希望能改成类似于asgif这种调用方法,这个又需要使用到glide自带的APT技术了,换句话说我们需要使用一个注解。这里我们新建一个类,类名随意,然后使用一下@GlideExtension注解,这里需要注意的是,类中必须要有一个私有无参构造方法,不然glide是会报错的。然后我们自定义一个asGif2方法,使用@GlideType进行标注,在里面就调用requestBuilder.apply方法就好了。写完以后要编译一下,让glide通过注解生成该方法,这样就可以直接调用了。
总结:glide优化其实就是指利用glide可以自定义解码器的特点,我们自己来定义并且注册了一个资源解码器,其中指定使用FrameSequence来进行解码,核心其实就是使用的giflib库。利用native层来实现资源的解码,提升了加载效率,其中我们还特意对bitmap进行了复用。然后为了调用方便,我们将调用方式从as改为asGif2,调用更加清晰明了。
相关文章:

Android 大图显示优化方案-加载Gif 自定义解码器
基于Glide做了图片显示的优化,尤其是加载Gif图的优化,原生Glide加载Gif图性能较低。在原生基础上做了自定义解码器的优化,提升Glide性能 Glide加载大图和Gif 尤其是列表存在gif时,会有明显卡顿,cpu和内存占用较高&…...
Leetcode.664 奇怪的打印机
题目链接 Leetcode.664 奇怪的打印机 hard 题目描述 有台奇怪的打印机有以下两个特殊要求: 打印机每次只能打印由 同一个字符 组成的序列。每次可以在从起始到结束的任意位置打印新字符,并且会覆盖掉原来已有的字符。 给你一个字符串 s ,你…...

正中优配:散户怎么实现T+0?散户在股市上怎么变相T+0?
T0是指当天买入的标的物,在当天就能卖出的买卖方式,其中,在a股市场上,散户能够通过一些办法直接地完成T0买卖方式,接下来,正中优配为大家预备了相关内容,以供参阅。 散户在股票市场上࿰…...

ZooInspector
一、在window,使用我们先打开Zookeeper,目录bin下的zkServer.cmd,把Zookeeper运行起来 编辑https://img.111com.net/attachment/art/187687/5f0c25fbe580c.png 二、可以使用目录bin下的zkCli.cmd,查询Zookeeper数据的方式,但是…...

2023高教社杯 国赛数学建模B题思路 - 多波束测线问题
1 赛题 B 题 多波束测线问题 单波束测深是利用声波在水中的传播特性来测量水体深度的技术。声波在均匀介质中作匀 速直线传播, 在不同界面上产生反射, 利用这一原理,从测量船换能器垂直向海底发射声波信 号,并记录从声波发射到信…...
【计算机视觉 | 目标检测】arxiv 计算机视觉关于目标检测的学术速递(9 月 4 日论文合集)
文章目录 一、检测相关(8篇)1.1 Impact of Image Context for Single Deep Learning Face Morphing Attack Detection1.2 A Theoretical and Practical Framework for Evaluating Uncertainty Calibration in Object Detection1.3 What Makes Good Open-Vocabulary Detector: A…...
游戏优化注意点
特效性能分析: 1、粒子数量太多,这个会对CPU的耗时产生一定的压力。 2、粒子的size太大,这样容易导致渲染的像素数量非常高。 3、Overdraw非常高,当场上粒子数非常高导致叠层很高,会造成Overdraw很高,这会…...

【unity3D】如何修改相机的默认视角
💗 未来的游戏开发程序媛,现在的努力学习菜鸡 💦本专栏是我关于游戏开发的学习笔记 🈶本篇是unity的如何修改相机的默认视角 如何修改相机的默认视角 Game窗口运行的话视角是这样的: 此时Scene窗口的视角是这样的&…...
Docker的初级使用
Docker的初级使用 Docker的安装1.1 如果之前安装过旧版本的Docker,可以使用下面命令卸载:1.2.安装docker1.3.启动docker1.4.配置镜像加速2.CentOS7安装DockerCompose2.1.下载2.2.修改文件权限2.3.Base自动补全命令:3.Docker镜像仓库3.1.简化版镜像仓库3.2.带有图形化界面版本…...
minimumLineSpacing和minimumInteritemSpacing问题研究
结论:minimumLineSpacing和minimumInteritemSpacing问题研究 (1)如果cell的宽度是固定的,方向是水平时, 1 3 5 2 4 6 minimumLineSpacing 是 12 到 34的距离 minimumInteritemSpacing 是1到2的距离 (2)如果cell的宽度是不固定的࿰…...

【操作系统】聊聊Linux内存工作机制
内存主要是用来存储系统和应用程序的指令、数据、缓存等 内存映射 内存是需要安全机制保护的,所以只有内核才可以直接访问物理内存。进程如果要访问内存需要通过独立的虚拟地址空间。 虚拟地址空间其实包含两部分。一部分是内核空间,另一部分就是用户…...
MySQL索引的类型有哪些?
分析&回答 从功能逻辑角度,可分为: 普通索引 INDEX(普通索引) ALTER TABLE table_name ADD INDEX index_name ( column )唯一索引 UNIQUE(唯一索引) ALTER TABLE table_name ADD UNIQUE (column)主键索引 PRIMARY KEY(主键索引…...

【JavaScript】在指定dom元素前面创建标签元素
一、基础操作过程 要在指定的DOM元素前面创建标签元素,有以下步骤: 获取指定的DOM元素:使用document.querySelector()或document.getElementById()等方法来获取指定的DOM元素。 const targetElement document.querySelector(#targetElement…...

ARMv8 TTBRx寄存器
ARMv8 TTBRx寄存器 1 TTBR0_ELx and TTBR1_ELx2 TTBR0_ELx2.1 TTBR0_EL12.2 TTBR0_EL22.3 TTBR0_EL33 TTBR13.1 TTBR1_EL13.2 TTBR1_EL2 4 访问TTBRx寄存器4.1 TTBR0_ELx4.2 TTBR1_ELx 5 TTBRx保留的是物理地址还是虚拟地址5.1 保存的是物理地址还是虚拟地址5.2 为什么是物理地…...

C51智能小车(循迹、跟随、避障、测速、蓝牙、wifie、4g、语音识别)总结
目录 1.电机模块开发 1.1 让小车动起来 1.2 串口控制小车方向 1.3 如何进行小车PWM调速 1.4 PWM方式实现小车转向 2.循迹小车 2.1 循迹模块使用 2.2 循迹小车原理 2.3 循迹小车核心代码 3.跟随/避障小车 3.1 红外壁障模块分析编辑 3.2 跟随小车的原理 3.3 跟随小…...

回归预测 | MATLAB实现PCA-BP主成分降维结合BP神经网络多输入单输出回归预测
回归预测 | MATLAB实现PCA-BP主成分降维结合BP神经网络多输入单输出回归预测 目录 回归预测 | MATLAB实现PCA-BP主成分降维结合BP神经网络多输入单输出回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 MATLAB实现PCA-BP主成分降维算法结合BP神经网络多输入单输出回…...

Kubernetes(k8s)部署高可用多主多从的Redis集群
Kubernetes部署高可用多主多从的Redis集群 环境准备准备Kubernetes准备存储类 部署redis准备一个命名空间命令创建yaml文件创建(推荐) 准备redis配置文件准备部署statefulset的资源清单文件执行文件完成部署初始化集群 环境准备 准备Kubernetes 首先你…...

算法专题:前缀和
文章目录 Acwing:前缀和示例2845.统计趣味子数组的数目思路容易理解的写法:前缀和两层循环存在问题:超时 优化写法:两数之和思路,转换为哈希表 前缀和,就是求数组中某一段的所有元素的和。 求子数组中某一…...

bs4库爬取天气预报
Python不仅用于网站开发,数据分析,图像处理,也常用于爬虫技术方向,最近学习了解下,爬虫技术入门一般先使用bs4库,爬取天气预报简单尝试下。 第一步:首先选定目标网站地址 网上查询,…...

l8-d8 TCP并发实现
一、TCP多进程并发 1.地址快速重用 先退出服务端,后退出客户端,则服务端会出现以下错误: 地址仍在使用中 解决方法: /*地址快速重用*/ int flag1,len sizeof (int); if ( setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &a…...

19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...