1. 内存泄漏类型html
本次内存优化,发现以下内存泄漏类型:java
Bitmap未即时释放缓存
Handler泄漏ide
static成员泄漏优化
Callback泄漏spa
Activity leak window设计
cursor未关闭htm
内存泄漏问题详细描述,参见《内存优化评估文档》。对象
下面将描述不一样内存泄漏类型的解决方案。blog
2. 内存泄漏解决方案
业务代码没有及时主动释放Bitmap,容易形成短期内内存被大量占用,进一步诱发OOM的发生。
解决方案思路有两种状况:
1) 对于从文件系统加载、Drawable资源加载,创建二级缓存管理该类Btimap;
2) 对于内存建立、图形变换产生的Bitmap,由业务本身去即时释放资源。
ImageUtis、BitmapUtils封装了Bitmap加载/获取的二级缓存机制,加载文件系统的Bitmap,推荐使用ImageUtils中的getBitmap系列方法。
调用ImageUtis获取Bitmap
图1描述了使用二级缓存管理Bitmap。
图1使用二级缓存管理Bitmap
自行管理Bitmap
图2描述了自行管理Bitmap释放。
图2自行管理Bitmap释放
Handler泄漏的缘由,大可能是匿名构建Handler实例,从而持有外部类Activity实例致使。
解决方案思路有两种:
1)去除Handler实例持有的外部类引用,该类思路的作法,通常是将Handler的子类定义为静态内部类,或者以一个单独的类文件形式存在;
2)保证在Activity/Service退出时,清空消息队列中与Handler有关的全部消息。
推荐使用第一种思路,实现起来简单、高效,第二种思路虽也可实现,但要考虑的面比较多,容易产生遗漏。
图3描述了MyCellLayout.java文件中,有一个Handler泄漏实例。
图3 Handler泄漏实例
图4中所示代码对图3中的Handler泄漏作了修复。
图4 图3 Handler泄漏修复
Static类成员,其生命周期与App生命周期近乎等长,在不合理的设计中,static类成员持有的对象,其内部持有Activity实例等致使。
解决方案思路有两种:
5)在static类成员持有的对象内部, 规避持有Activity实例;
6)避免使用static成员。
图5描述了 GlobalMsgProcessHelper.java中static类成员泄漏。
图5 static类成员泄漏
图6是对图5 static类成员泄漏的修复。
图6 图5 static类成员泄漏修复
Callback直接或间接持有Activity实例等致使。
解决方案思路,在Callback对象内部规避持有Activity实例。
参见DeviceCategoryView.java DeviceCategoryDownloadCallback。
Activity异外先于Dialog退出,致使本异常抛出,本质也是一种内存泄漏。
构建BaseDialog,使全部自定义Dialog均扩展自此类,在BaseDialog内部实如今Activity退出前先行销毁的逻辑。
图7 描述了BaseDialog实现自释放逻辑。
图8 描述了CommonDialog派生自BaseDialog
图7 BaseDialog实现自释放逻辑
图8 CommonDialog派生自BaseDialog
Cursor使用完后等致使。
解决方案思路,在Cursor使用完后释放资源。
图9描述了Cursor泄漏修复。
图9 Cursor泄漏修复