【性能优化】Bitmap的优化

1,121 阅读2分钟

由于jvm分配给每个应用的运行内存是有限的,如果加载的图片过大,很有可能回导致oom。 并且在平时的项目中,一般要加载的图片的尺寸远远大于imageview控件的尺寸,如果按照原图显示的话, 会造成资源的浪费。

所以我们在加载图片优化时,通常做的做法就是图片压缩,和图片缓存。

如何计算一个Bitmap占用内存的大小

内存大小 = 宽度像素 x (inTargetDensity / inDensity) x 高度像素 x (inTargetDensity / inDensity)x 一个像素所占的内存

Bitmap 在内存当中占用的大小其实取决于:

  • 色彩格式,前面我们已经提到,如果是 ARGB8888 那么就是一个像素4个字节,如果是 RGB565 那就是2个字节

  • 原始文件存放的资源目录(是 hdpi 还是 xxhdpi 可不能傻傻分不清楚哈)

  • 目标屏幕的密度(所以同等条件下,红米在资源方面消耗的内存肯定是要小于三星S6的)

注:放在drawable目录下的图片可能会进行拉伸,而放在存储空间内的不会进行拉伸。这里inDensity表示目标图片的dpi(放在哪个资源文件夹下),inTargetDensity表示目标屏幕的dpi,所以你可以发现inDensity和inTargetDensity会对Bitmap的宽高进行拉伸,进而改变Bitmap占用内存的大小。

在Bitmap里有两个获取内存占用大小的方法。

getByteCount():API12 加入,代表存储 Bitmap 的像素需要的最少内存。 getAllocationByteCount():API19 加入,代表在内存中为 Bitmap 分配的内存大小,代替了 getByteCount() 方法。 在不复用 Bitmap 时,getByteCount() 和 getAllocationByteCount 返回的结果是一样的。在通过复用 Bitmap 来解码图片时,那么 getByteCount() 表示新解码图片占用内存的大 小,getAllocationByteCount() 表示被复用 Bitmap 真实占用的内存大小(即 mBuffer 的长度)。

Android 开发绕不过的坑:你的 Bitmap 究竟占多大内存?

不同的drawable文件夹下图片加载到内存后图片尺寸大小的分析

图片压缩

1 选择合适的图片格式(bitmap格式)

ALPHA_8 每个像素占用1byte内存        
ARGB_4444 每个像素占用2byte内存       
ARGB_8888 每个像素占用4byte内存(默认)      
RGB_565 每个像素占用2byte内存

2 质量压缩和像素压缩(尺寸压缩)

  • 质量压缩: 通过bitmap.compress压缩图片质量,
  • 像素压缩:通过BitmapFactory.Options()设置inSampleSize采样率压缩图片大小

图片压缩的两种方式

3. 图片复用

弱引用和缓存池LurCache和DiskLruCache

LruCache

4. 将Bitmap放在native层

5. Bitmap使用完及时使用recycle方法回收内存