最近重构项目时,显示图片的列表特别多,AS捕捉下来的内存,Bitmap使用的内存占比多,所以做BitMap优化,记录一下Bitmap优化思路,代码太多就不贴了。
Bitmap优化思路
-
Bitmap内存占用
-
内存大小计算,有两种常用格式:ARGB_8888,RGB_565
- ARGB_8888:各占8位,共32位,即占4个字节;内存大小:宽乘高乘以4
- RGB_565:共16位,即占2个字节;内存大小:宽乘高乘以2
-
获取Bitmap所占用的内存
- 调用getByteCount(),返回可用于存储此位图像素的最小字节数
- 系统分配给Bitmap的内存大小:Bitmap.getAllocationByteCount()
-
Bitmap内存压缩
-
通过BitmapFactory.options的配置参数改变
inJustDecodeBounds:为true时,解析将返回null,但是只会解析outxxx参数。
inPreferredConfig:设置图片解码的像素格式,如ARGB_8888,RGB_565
采样率inSampleSize:设置图片解码缩放比,如值为2,则加载图片的宽高是原来的1/2,整个图片所占用内存的大小为原图的1/4。
-
-
-
Bitmap缓存(内存缓存+磁盘缓存)
-
使用LruCache(最近最少使用缓存)
- 通过ActivityManager.getMemoryClass()获取内存总大小,并计算LruCache可缓存最大内存为:总内存除以8乘以1024乘以1024,在LruCache可以进行Bitmap缓存、获取、移除。
- 在LruCache的sizeOf()中如果是4.4版本则返回Bitmap.getAllocationByteCount系统分配给Bitmap的内存大小,否则返回Bitmap.getByteCount此图片的最小内存大小。
- 从内存中(LruCache.entryRemoved方法会监听)移除的Bitmap,如果Bitmap是否易变(设置了isMutable为true)如果易变则用弱引用封装Bitmap后,存入复用池Set集合。注意:在3.0版本Bitmap是缓存在Native;在8.0版本之前Bitmap是缓存在java ;在8.0之后Bitmap是缓存在Native。放在有java和Native的区别:从Nativ移到Java可以是为了方便管理(JVM好管理一些),可能觉得占用空间,又移回Native中,如果是在JVM中,GC我们不用管,但在Native中则要代码中手动释放Bitmap。所以在创建弱引用时,要创建一个引用队列,如果referenceQueue.remove时,如果referenceQueue中的Bitmap没有释放则手动释放。
- 对外提供一个可复用方法,从复用池中取出Bitmap检查是否可以复用,如果可复用返回Bitmap并从复用池中移除,反之返回null。注意Bitmap复用的规则:3.0版本之前不能复用;3.0~4.4版本宽高一样,并且inSampleSize为1;4.4版本只要小于等于系统分配Bitmap内存大小。
使用DiskLruCache进行磁盘缓存Bitmap存入和读取。
-
记录语
记录Bitmap优化思路,方便日后提供温习。