内存优化
意义:减少因为频繁GC导致的卡顿,减少因为内存占用应用存活率降低
内存问题
- 内存抖动:表现为内存锯齿状,频繁GC,导致卡顿
- 内存泄露:可用内存减少,频繁GC
- 内存溢出:OOM、程序异常
相关工具的使用
Dalvik
与 Art
的区别
Dalvik
仅固定一种回收算法Art
回收算法可运行期切换,具备内存整理能力,减少内存空洞
Low Memory Killer
- 进程分类(优先级从高到低):前台进程、可见进程、服务进程、后台进程、空进程
- 回收收益:系统会考虑回收收益执行回收力度
内存抖动
内存频繁分配和回收导致内存不稳定,频繁
GC
,易导致卡顿和OOM
频繁创建对象、释放对象,导致内存碎片化严重
不连续的内存片无法被分配,导致 OOM
解决技巧:通过 Memory Profiler
找对象,重点寻找循环或者频繁调用的地方
【注意】内存泄漏造成内存减少,也会出现频繁回收对象而出现内存抖动
内存泄漏
dump
出的内存文件通过 Memory Analyzer
工具进行分析
大图监控
由于图片是占用内存的大头,所以必须对其严格控制,可以使用 AOP
或 ART
方式获取相应控件的大小和 Bitmap
的大小,提前警告
线上内存监控
- 常规方案:超过最大内存80%,
Dump
内存,待到wifi
环境下回传文件分析Dump
文件太大,和对象数正相关,可剪裁- 文件较大上传失败率高,分析困难
- 效果有限
LeakCanary
线上监控,预设怀疑点,发现泄漏回传- 不适合所有场景,需要预设坏一点
- 该库分析比较耗时,容易OOM
- 建议定制
LeakCanary
线上监控完整方案
- 待机内存、重点模块内存、OOM率
- 整体及重点模块GC次数、GC时间
- 增强
LeakCanary
自动化内存泄漏分析
优化大方向
- 内存泄漏
- 内存抖动
- Bitmap
优化细节
设置
LargeHeap
属性,向系统申请更多内存系统回调
onTrimMemory
根据回调级别做适当的资源释放,当系统回调严重级别时可以将所有界面关闭强制重启主界面的操作使用优化过的集合:
SparseArray
、ArrayMap
,性能虽不及HashMap
,但在数据量较少的情况下是可以接受的谨慎使用
SharedPreference
,首次加载时会将涉及的文件所有数据加载到内存里,如果单个文件过大造成内存占用过多可以考虑使用
IntDef
StringDef
来减少枚举类型的使用谨慎使用外部库
尽可能使用静态内部类减少外部引用
图片优化
- 对图片质量要求不高的可以适当降低图片质量,如 ARGB_4444 或 RGB_565
- 适当对图片进行缩小加载
- 重用 Bitmap 内存
- 类似 Glide 图片加载库,默认兼容 gif 和 webp,但是执行效率和内存使用率并不高,可以接入 giflib 和 libwebp 进行优化
- Item 被回收不可见时释放图片的引用
ListView
:条目被回收后都会重新绑定数据,只需要在ImageView.onDetachFromWindow()
时释放图片引用RecycleView
:当条目不可见时优先放入mCacheView
缓存中,重新展示并不会触发bindViewHolder
来绑定数据,只有被收录到mRecyclePool
中才会拿出来复用并绑定,需要在Adapter.onViewRecycled()
函数中释放图片引用,该函数会在条目收录到mRecyclePool
缓存时回调