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…...

深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
React---day11
14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store: 我们在使用异步的时候理应是要使用中间件的,但是configureStore 已经自动集成了 redux-thunk,注意action里面要返回函数 import { configureS…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...

iview框架主题色的应用
1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题,无需引入,直接可…...

三分算法与DeepSeek辅助证明是单峰函数
前置 单峰函数有唯一的最大值,最大值左侧的数值严格单调递增,最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值,最小值左侧的数值严格单调递减,最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...
Leetcode33( 搜索旋转排序数组)
题目表述 整数数组 nums 按升序排列,数组中的值 互不相同 。 在传递给函数之前,nums 在预先未知的某个下标 k(0 < k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nu…...
【实施指南】Android客户端HTTPS双向认证实施指南
🔐 一、所需准备材料 证书文件(6类核心文件) 类型 格式 作用 Android端要求 CA根证书 .crt/.pem 验证服务器/客户端证书合法性 需预置到Android信任库 服务器证书 .crt 服务器身份证明 客户端需持有以验证服务器 客户端证书 .crt 客户端身份…...