《Android高性能编程》-提升技能的小技巧

《Android高性能编程》-提升技能的小技巧

2018, Apr 28    

位图

加载

BitMap.createScaledBitmap()方法在创建一个新的小图像之前,都会读取整个原图,造成了非必要的内存分配。一旦我们明确了图像要被缩放的分辨率,可以利用BitmapFactory.Options类,通过设置参数,高效地缩放图像。
BitmapRegionDecode类可以得到部分图像
流程:(file可以换为bytearray, resource, stream等)

  1. 加载(不处理位图)injustdecodebounds = true
  2. 读取图片分辨率 decodefile
  3. 计算比率 outHeight/desiredheight等
  4. 设置属性 insampleSize(为2的倍数,因为工作原理是从相邻的四个像素矩阵中取出一个像素)
  5. 加载 decodefile(url, options)

缩小到精确的尺寸: inScaled, inDensity, inTargetDensity
需要以牺牲速度为代价,最好的方案是结合两种。第一种方案计算比率之后,用第二种方案的设置方法

处理

必须在工作线程中
使用weakReference持有ImageView,否则会带来activity泄漏
回收时要判断view是否被weakreference是否被引用

缓存

算法LRU,优先级:被使用的再栈顶,其余按照请求次数
LRUCache对象是线程安全的
将应用程序的部分可用控件提供给缓存使用 (Runtime.getRuntime().maxMamery()),此类缓存处于堆内存中,退出activity再进入后图片不存在。
DiskLRUCache,不是线程安全的,在使用时需要加锁,在工作线程中执行,(Disk-level cache可以持久化,速度慢,如果堆级别缓存中不存在,会再检查磁盘级别; Heap-level cache)当想要将图像加入缓存时,需要同时添加两种缓存。

显示

四种像素格式:
ARGB_8888:每个像素使用32bit,每个通道8bit
ARGB_4444:每个通道仅使用4像素,节省一半的内存空间,但显示效果糟糕
RGB_555:只保留颜色通道,移除了alpha值,红色蓝色5bit,绿色6bit,每个像素使用16bit,处理非透明度图片
ALPHA_8:仅储存透明信息,没有颜色通道
bitmapFactory.option.inpreferredConfig定义像素格式。会消耗更多的计算时间和CPU消耗

管理内存

对象池模式,重用已分配内存,来处理新图像的显示
BitmapFactory.Options.inBitmap, 使用该属性,需要提供一个已存在的位图对象,让解码器重用该对象的内存空间,这样,就对象没有被销毁,新对象也没有被创建,就不需要垃圾回收了
限制:18以前必须尺寸相同,19开始可以大于等于;不同像素格式的图像,不应被用于此种操作

  1. 判断内存大小
    内存 = 被压缩后的宽(options.outwidth/options.insamplesize) ✖️高 ✖️ 每像素的内存
  2. 对象池中检索。Set < SoftReference < Bitmap > >
  3. 创建方法,在图像解码钱,添加option以重用对象(options.inMutable) #图像优化 #序列化 #代码改进 #AndroidN中的java8 #APK优化