-
避免内存泄露
内存泄露是造成OOM的最主要原因 常见的内存泄露: 1. 单例 因为单例是全生命周期的,如果引用了非全生命周期变量,就会导致内存泄露 2. 静态变量 同样也是生命周期长 3. Handler 因为非静态内部类会持有外部类的引用,Activity destroy之后由于消息队列还存在消息,handle对象无法被回收,就造成activity也无法销毁;解决方案是使用静态内部类创建handle,并在页面退出的时候清空消息队里 4. 资源使用完未关闭 比如BraodcastReceiver,ContentObserver io流 bitmap等等;解决方案就是及时关闭释放 开发阶段可以使用工具来实时监测我们的程序是否有内存泄露:LwakCanary
-
优化图片的内存占用
除了内存泄露,引发oom的第二大问题就是图片的内存占用 1. bitmap 有时候我们需要直接对bitmap进行操作,可以基于软引用自己实现一个bitmap缓存池,这样对于同一个图片,bitmap对象会重复使用(例如默认图);这也是glide内部的做法;我们在使用context.getResources().getDrawable获取图片时,系统内部也维持了一个bitmap缓存池(由算法处理,一般是lru算法) 2. 图片压缩 在使用BitmapFactory解码时,我们可以通过配置参数对待加载的图片进行调整,一般有降低分辨率、改变加载模式(ARGB_8888==>RGB565)等 3. 在低级设备上加载更小的图片,比如使用纯色背景,使用更低分辨率的图片
-
避免内存抖动
内存在频繁的分配和回收时会造成gc频繁工作,会导致卡顿,严重时会引发OOM 例如在循环中频繁拼接String对象,会造成内存抖动;解决方案是采用StringBuffer和StringBuilder
-
其它优化
除了以上几个比较大的情况会引发内存问题外,还有一些其它细节也会引发内存问题,需要有针对性的优化 1. 数据结构优化 在Android中使用SparseArrayMap和ArrayMap替代HashMAp 2. 避免使用枚举 3. 列表复用(listview和recycleview) 4. 减少是视图的层级 1. 使用constraintlayout替代线性布局和相对布局 2. 使用viewstub标签延迟初始化视图 5. 将一些复杂计算及占用内存的操作放到native层处理,比如音视频解码
工具
- LeakCanary监测内存泄露
- MAT分析内存占用
- Android监测内存实时情况,监测内存抖动