Android App 性能优化之图片优化

2023-10-31

接下来说明一下关于其他内存问题。图片问题,作为一个优秀的Android开发者,在图片的类型选择,图片显示前的处理都是要好好考虑的,因为不同类型图片在Android中的显示代价是不同的,使用不同显示方式代价也是不同的,首先看一下图片类型png与jpg两种类型显示代价有不同,原因在于png占的内存较多,但解码叫简单,若png图片过多,会容易垃圾回收,甚至内存溢出,而jpg的内存小,但解码复杂,会花更多时间解码,所以要根据具体情况来定,如果当前是由于内存问题导致垃圾回收频繁执行导致卡慢顿,这样图片优化就减少png,如果是非内存问题导致的,就可以使用png。

谷歌官方说法如下:

Smaller PNG Files(较少的png文件)

尽量减少PNG图片的大小是Android里面很重要的一条规范。相比起JPEGPNG能够提供更加清晰无损的图片,但是PNG格式的图片会更大,占用更多的磁盘空间。到底是使用PNG还是JPEG,需要设计师仔细衡量,对于那些使用JPEG就可以达到视觉效果的,可以考虑采用JPEG即可。

谷歌官方这样说应该是由于Android上导致卡慢顿的大多数原因是和内存有关吧。

关于在图片显示前的操作:

Pre-scaling Bitmaps(预放缩图片)

bitmap做缩放,这也是Android里面最遇到的问题。对bitmap做缩放的意义很明显,提示显示性能,避免分配不必要的内存。Android提供了现成的bitmap缩放的API,叫做createScaledBitmap(),使用这个方法可以获取到一张经过缩放的图片。

 

上面的方法能够快速的得到一张经过缩放的图片,可是这个方法能够执行的前提是,原图片需要事先加载到内存中,如果原图片过大,很可能导致OOM。下面介绍其他几种缩放图片的方式。

inSampleSize能够等比的缩放显示图片,同时还避免了需要先把原图加载进内存的缺点。我们会使用类似像下面一样的方法来缩放bitmap

 

 

另外,我们还可以使用inScaledinDensityinTargetDensity的属性来对解码图片做处理,源码如下图所示:

 

(注:这里的bitmapoption还可以知道图片的编码类型)

还有一个经常使用到的技巧是inJustDecodeBounds,使用这个属性去尝试解码图片,可以事先获取到图片的大小而不至于占用什么内存。如下图所示:




Re-using Bitmaps(重复使用bitmaps)

我们知道bitmap会占用大量的内存空间,这节会讲解什么是inBitmap属性,如何利用这个属性来提升bitmap的循环效率。前面我们介绍过使用对象池的技术来解决对象频繁创建再回收的效率问题,使用这种方法,bitmap占用的内存空间会差不多是恒定的数值,每次新创建出来的bitmap都会需要占用一块单独的内存区域,如下图所示:

 

为了解决上图所示的效率问题,Android在解码图片的时候引进了inBitmap属性,使用这个属性可以得到下图所示的效果:

 

使用inBitmap属性可以告知Bitmap解码器去尝试使用已经存在的内存区域,新解码的bitmap会尝试去使用之前那张bitmapheap中所占据的pixel data内存区域,而不是去问内存重新申请一块区域来存放bitmap。利用这种特性,即使是上千张的图片,也只会仅仅只需要占用屏幕所能够显示的图片数量的内存大小。下面是如何使用inBitmap的代码示例:

 

使用inBitmap需要注意几个限制条件:

·在SDK 11 -> 18之间,重用的bitmap大小必须是一致的,例如给inBitmap赋值的图片大小为100-100,那么新申请的bitmap必须也为100-100才能够被重用。从SDK 19开始,新申请的bitmap大小必须小于或者等于已经赋值过的bitmap大小。

·新申请的bitmap与旧的bitmap必须有相同的解码格式,例如大家都是8888的,如果前面的bitmap8888,那么就不能支持4444565格式的bitmap了,不同的编码格式占用的内存是不同的,有时候也可以根据需求指定编码格式。

我们可以创建一个包含多种典型可重用bitmap的对象池,这样后续的bitmap创建都能够找到合适的“模板”去进行重用。如下图所示:

 

Google介绍了一个开源的加载bitmap的库:Glide,这里面包含了各种对bitmap

 

前面提到编码方式,其实不同的编码方式占用内存是不同的当然显示效果也是有区别的,可以在不影响用户体验的前提下,适当选择编码方式。

 Smaller Pixel Formats

常见的png,jpeg,webp等格式的图片在设置到UI上之前需要经过解码的过程,而解压时可以选择不同的解码率,不同的解码率对内存的占用是有很大差别的。在不影响到画质的前提下尽量减少内存的占用,这能够显著提升应用程序的性能。

AndroidHeap空间是不会自动做兼容压缩的,意思就是如果Heap空间中的图片被收回之后,这块区域并不会和其他已经回收过的区域做重新排序合并处理,那么当一个更大的图片需要放到heap之前,很可能找不到那么大的连续空闲区域,那么就会触发GC,使得heap腾出一块足以放下这张图片的空闲区域,如果无法腾出,就会发生OOM。如下图所示:

 

所以为了避免加载一张超大的图片,需要尽量减少这张图片所占用的内存大小,Android为图片提供了4种解码格式,Android默认是使用argb8888格式,还有argb4444,alpha8及rgb565:

 对于不同解码格式占用内存大小具体如下:

Bitmap.Config ARGB_4444:每个像素占四位,即A=4R=4G=4B=4,那么一个像素点占4+4+4+4=16

 

Bitmap.Config ARGB_8888:每个像素占四位,即A=8R=8G=8B=8,那么一个像素点占8+8+8+8=32

 

Bitmap.Config RGB_565:每个像素占四位,即R=5G=6B=5,没有透明度,那么一个像素点占5+6+5=16

 

Bitmap.Config ALPHA_8:每个像素占四位,只有透明度,没有颜色。

 

一般情况下我们都是使用的ARGB_8888,由此可知它是最占内存的,因为一个像素占32位,8=1字节,所以一个像素占4字节的内存。假设有一张480x800的图片,如果格式为ARGB_8888,那么将会占用1500KB的内存。

 


随着解码占用内存大小的降低,清晰度也会有损失。我们需要针对不同的应用场景做不同的处理,大图和小图可以采用不同的解码率。在Android里面可以通过下面的代码来设置解码率:

 

实际上,一张图片在内存中占用多大空间主要受图片本身大小(分辨率),解码方式,还有就是设备像素密度这三个因素影响,其中像素密度是由设备定的,编程人员可控性不高。所以解决一张图片在内存中大小问题,就得从图片分辨率和解码方式入手。


注意:

Bitmap 对象在不使用时,我们应该先调用recycle()释放内存,然后才置空,因为加载bitmap对象的内存空间,一部分是java的,一部分是c的(因为Bitmap分配的底层是通过jni调用的,BitMap底层是skia图形库,skia图形库是c实现的,通过jni的方法在java层进行封装)。这个recycle()函数就是针对c部分的内存释放。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android App 性能优化之图片优化 的相关文章

随机推荐

  • 【马士兵】Python基础--17

    Python基础 17 文章目录 Python基础 17 特殊方法和特殊属性 new init 类的赋值与浅拷贝 知识点总结 特殊方法和特殊属性 print dir object class delattr dir doc eq forma
  • Python运维开发工程师养成记(for循环语句)

    图示 案例 通过列表索引迭代 循环使用 else 语句 好了 今天学习到这里 下节开始学习python循环嵌套 链接 https ke qq com course 4300856 tuin d8aedf68
  • 【云原生之Docker实战】使用Docker部署MongoDB数据库管理工具Mongo-Express

    云原生之Docker实战 使用Docker部署MongoDB数据库管理工具Mongo Express 一 Mongo Express介绍 1 Mongo Express简介 2 MongoDB简介 二 检查本地系统环境 1 检查系统版本 2
  • 基于tcpdump实例讲解TCP/IP协议

    http www cnblogs com ggjucheng archive 2012 02 02 2335495 html 前言 虽然网络编程的socket大家很多都会操作 但是很多还是不熟悉socket编程中 底层TCP IP协议的交互
  • 树的遍历之B树及其变种

    文章目录 1 基本概念 1 1 B树的引进 1 2 B树的定义 1 3 B树的举例 2 B 树 3 B 树 4 总结 1 基本概念 1 1 B树的引进 我们发现 之前的二叉树 AVL 2 3树 这些树每一个节点所存储的数值量就只有一个 而这
  • 【Proteus仿真】【STM32单片机】智能手环

    文章目录 一 功能简介 二 软件设计 三 实验现象 联系作者 一 功能简介 系统运行后 OLED显示温度 心率 加速度极其阈值 可按下K3键进入阈值设置模式 K1和K2调节对应阈值 K4确定 当检测体温 心率 加速度超出阈值范围 则蜂鸣器报
  • vim常用命令总结(ideavim)

    vim常用命令总结 ideavim vim常用命令总结ideavim 插入命令 删除命令 复制命令 选中命令 光标移动 功能命令 标记命令 1 插入命令 i 命令可以在当前光标之前插入文本 I 命令可以在当前行首插入文本 a 命令可以在当前
  • sudo 命令无法使用

    1 不能使用sudo命令解决方法 想查看这个用户可以使用哪些sudo命令 输入正确密码却不能查看 原因就是在 etc sudoers中未添加该用户 xm oracle sudo l sudo password for xm Sorry us
  • adb 读取短信,通话记录、日历、通讯录等的方法

    读取手机短信 adb shell content query uri content sms 这将列出所有短信消息的详细信息 例如短信内容 发送者和接收者的电话号码 时间戳等 读取手机通话记录 adb shell content query
  • MainWindow 简介

    致介绍了 Qt 各个模块的相关内容 目的是对 Qt 框架有一个高屋建瓴般的了解 从现在开始 我们将开始尝试使用 Qt 开始新的历程 由于我们已经比较详细地介绍过信号槽的相关内容 因此我们可以用一个新的程序开始进一步的学习 同时对信号槽有一个
  • 【Unity3D小功能】Unity3D中实现Text显示版本功能

    推荐阅读 CSDN主页 GitHub开源地址 Unity3D插件分享 简书地址 我的个人博客 大家好 我是佛系工程师 恬静的小魔龙 不定时更新Unity开发技巧 觉得有用记得一键三连哦 一 前言 在项目开发中 会遇到要控制版本的情况 比如说
  • Excel只能做表格?那是你不会用!10分钟做出高大上可视化图

    点击进入看图评论 很多公司都要求员工熟练的掌握Excel But 绝大多数人所谓的熟练使用Excel 估计也只会一些简单的表格和知道加减乘除 求和吧 再难一点 估计就真的把自己难倒了 讲真 Excel还是很牛的 只是你不会 话不多说 今天就
  • 解决Hbuilder打包的app返回键直接退出

    问题描述 Hbuilder打包的app如果点击手机返回键 app会直接退出 返回不了上一页 处理子页面点击返回键直接退出 无法返回 代码如下 这个不是写在首页 写在子页面 子页面才能返回 写在首页点击返回就是退出 不用引入mui js 都是
  • stc51单片机串口接收多字节数据

    stc51单片机串口接收多字节数据 简介 51单片机有2个定时器 一个做串口波特率 一个做数据截止帧延时检测 硬件平台测试使用的是stc8的单片机 但是可以往51移植 代码 include stc8 h unsigned char flag
  • 字典序排数相关算法

    记录两道与数字的字典序排数相关的题目 字节常考 把数字的字典序画出来看看马上就明白了 class Solution public List
  • 企业——企业架构的基本数据流向

    一 数据流向 1 基本的数据流向 client gt server 直接由客户端流向服务端 在实际生产环境中因为访问量大 服务器承受不了压力 因此基本不会使用 2 企业架构的数据流向 企业采用分布式的数据流向 cdn 缓存加速reverse
  • STM32中断定时,控制LED灯

    1 include led h 2 3 void TIM3 Int Init u16 arr u16 psc 4 5 TIM TimeBaseInitTypeDef TIM TimeBaseStructure 6 NVIC InitType
  • redis 由浅入深之 数据结构

    Redis 缓存数据所支持的数据结构如下 一 字符串 字符串 string是最简单的类型 你可以理解成与Memcached一模一样的类型 一个key对应一个value 其上支持的操作 与Memcache的操作类似 但它的功能更丰富 字符串指
  • JavaScript特殊的对象1:数组

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 一 为什么说数组是特殊的 对象 因为数组可以通过构造函数Array 创建 它的原型同样也是Array prototype 它的对象类型时Array 它具有自身属性lengt
  • Android App 性能优化之图片优化

    接下来说明一下关于其他内存问题 图片问题 作为一个优秀的Android开发者 在图片的类型选择 图片显示前的处理都是要好好考虑的 因为不同类型图片在Android中的显示代价是不同的 使用不同显示方式代价也是不同的 首先看一下图片类型png