Android开发高手进阶 -- 内存优化
内存优化需要理解的技术:
- hook gc来避免gc引起的memory churn的技术
- 常见的引起内存泄漏几种情况的解决
- 静态属性持有 activity 或者 view 等
- 内部类、匿名类持有activity或者view等外部类的引用
- Handler 提交msg的是否一个匿名的runnable 持有外部的引用
- Thread 和 timertask 由于thread 和timertask 会另外启动线程而线程在运行结束销毁之前是当做gcroot的
- 某些系统服务 比如sensormanager需要持有activity的的引用以作回调的
- 资源未回收关闭 导致的问题
- webview
- 数据结构优化(arraymap等)
- 更换序列化方案
- view复用
- object pool等优化方法
- 内存相关的操作系统概念
- Android虚拟机heap space的结构和allocator的执行原理
内存优化
为什么要优化内存,首先要降低应用的内存占用,这样有助于不被lmkiller 杀死,第二 提高应用的运行速度不会因为频繁gc而变卡
内存泄漏的主要原因,列举如下:
- 静态变量:监听器、广播、webview等
- 内部类:handler、timer、Thread等
- 系统:dialog、输入法、音频、textline
内存泄漏的监控方案
-
LealCanary:使用弱应用检查Activity的对象内存泄漏
-
可以通过 在activity destroy的时候手动释放各种资源,来避免activity泄漏导致activity所持有的资源没有被释放
-
Drawable d = iv.getDrawable(); if (d != null) { d.setCallback(null); } iv.setImageDrawable(null);
如何减少内存的占用
-
图片:
- 使用统一的图片加载库,方便修改加载方式
- .9图的修改 避免多余的像素加载浪费
- 图片加载不超过 view的大小
- bitmap不放在java堆中?
-
监控自己的内存使用
Runtime.getRuntime().maxMemory(); Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
这样获取到当前自己的内存占用,到达一个筏值的时候 释放一些资源比如 glide的释放模块
-
使用多进程,比如图库,比如webview所占用的内存
-
large heap: application 节点之下 android:largeHeap = true
-
inBitmap: BitmapFactory.Option.inBitmap应用了这个option的image 将会使用同一个bitmap的地方
-
SparseArray:key一个数组 value一个数组 代替map
-
ArrayMap:key的hash 保存成一个数组,key-value相隔 保存成一个数组,先通过key的hash获取到index 去读第二个数组,如果找不到 说明 产生了碰撞
-
Protobuf:T-L-V ,varint byte 数组表示,可以将一个较小的数用更低的位来代替 link
GC type
- GC_CONCURRENT 对象大于348k的时候会触发的gc 说明对象的复用不够
- GC_FOR_ALLOC 内存不足时会触发
- GC_EXPLICIT gc()
内存抖动
内存抖动,说明大量对象创建,大量对象被回收,频繁gc 会卡
- 字符串拼接优化
- 减少不必要或不合理的对象
- 使用合适的集合来替换雷士hashmap等集合
减少apk的包的体积将显著减少内存的占用
aapt crunch
在保存png的质量的同时缩减 png的大小
- aapt crunch
- aapt single-crunch