(九)图片预览内存优化实践

针对图片加载的内存优化过程

Posted by chchaooo on April 23, 2018

项目中包含一个如下的页面,其作用是对拍摄过的照片进行优化,包含一个大图预览和一个可以滑动的缩略图预览栏

使用Android Studio Profiler来进行内存的跟踪。先拍摄了700张照片用于预览,然后停留在预览页面,再采集结果中随机浏览了30分钟,每秒钟随机切换一张照片,整体的内存占用并没有上升迹象,这可以说明该过程中并没有内存泄漏,但是可以看到局部的内存波动很大

我们缩小时间维度来观察其中局部的内存变化细节:

(随机跳动,每次需要加载多张图片,峰值223.51MB,阶段低谷155.49MB)

(顺序滑动,加载的图片稍少一些)

可以看到每一秒钟内存会出现周期性变化,在没有发生GC的情况下,内存使用会增加7MB左右,当空余内存积累较多时,就会触发一次GC,内存占用会降下来。

每次预览都是重新申请一块内存以供解析图片使用,当需要展示新的图片时,就去申请新的内存,下面是对内存的使用情况进行的详细调查。在这个

只考查ReviewView的大图 隐藏下面的Recycleview缩略图栏,切换一次照片,可以看到内存的变化基本是增加3MB左右。以一张116.85kb的照片为例子,

  • 读取图片到byte数组:116,854bit长度
  • 通过byte数组生成bitmap对象:bitmap中buffer长度3,686,400byte

为啥不管什么图片,buffer大小都是3686400

此时多次滑动图片时,可以看到内存每次滑动基本都会递增3.6MB左右(除去发生GC时外)

为了方便统计,只考查ReviewView的大图的内存占用,隐藏下面的RecycleView缩略图,

使用inbitmap来对内存的占用进行优化(Bitmap内存管理),核心思想是重用bitmap,在仅仅优化ReviewView大图时,发现很好使,内存的变动小了很多,只剩下每次的读取文件的消耗。但是放开缩略图也显示的时候,内存的占用再次会出现大幅度增加,通过详细日志可以定位到缩略图的bitmap为360* 640,而大图的bitmap为720*1080,回收条件中,只要可复用bitmap的大小大于等于带显示的view均可用,此时缩略图可能会使用了大图的bitmap,导致大图自身只好重新申请内存来存储自身的bitmap

优化方案 重用的bitmap时只有当待重用的bitmap与待显示bitmap分辨率完全相同时,才会重用 这样的情况下,每秒钟切换一次照片,可以看到内存是在处于一个非常缓慢的照片增长过程中,占用情况如下图所示:

(图片峰值181.66MB,阶段低点157.6MB)

这个过程中的增长主要是解析新的照片所产生的byte数组,其中存在的大量突起就是byte数组的申请和局部GC。

(图片峰值161MB,阶段低点131MB)

继续优化使用一个固定的加载文件的bytearry而不是每次都重新申请一个新的来使用

此时内存占用处于稳定的低状态,GC发生的频率也很低。

  • 内存占用从从峰值223.51MB,阶段低谷155.49MB,降低到图片峰值161MB,阶段低点131MB,平均约降低了22.3%
  • GC频率从1分35秒内33次,降低到1分35秒内3次,降低了90.9%
  • 页面流程度的测算待续