OOM-关于Android内存溢出的一些解决思路的整理

发布于 2018-10-23  265 次阅读


原因:系统为每一个应用程序分配了不同的内存上限,如果超过这个上限被视为内存泄露,从而被kill掉。

比如:

1.加载对象过大

2.相应资源过多,来不及加载

解决办法们

oom这个真的不好权衡,下面这些注意事项好多是相互矛盾的,根据业务,各取所需吧。
而且一味的追求小内存开销,也不好。
毕竟,硬件本身的性能越来越强大,你不用,它也会老化。

一、图片

1.内存中加载图片直接在内存中做处理(如边界压缩)
2.减少Bitmap对象的内存占用

1.加载之前先计算出合适的缩放比例
2.选择合适的解码格式:ARGB_8888/RBG_565/ARGB_4444/ALPHA_8,内存在很大差异。
(比如:带 alpha通道的图片,每个像素的要多消耗2字节的内存

3.临时Bitmap的及时回收

二、对象

1.动态回收内存
2.内存引用上做一些处理。(eg:软引用)
3.对象的复用

1.复用系统自带的资源:字符串、图片、动画、样式、颜色、简单布局
2.列表(eg:ListView)中对视图的复用
3.实例对象的复用:inBitmap属性可以告知Bitmap解码器使用已经存在的内存区域而不是重新申请一块内存区域
4.避免对象的频繁创建(eg:在onDraw()、循环中创建对象等)
5.StringBuilder替代""+""的拼接
6.用Integer.toString代替String.valueOf(int)和 int+""; (因为String会做很多业务上不必要的判断。
(其实这应该算是性能问题了哈:)

4.当心对象的复用

比如static对象:因为这玩意和应用进程一样长命

5.注意单例模式中的不合理持有

虽然单例模式有效的避免了对象的多出创建,但缺点也在这里:
单例的生命周期和应用保持一致(static),使用不合理很容易出现持有对象的泄漏。(不能正常回收)

6.注意监听器的及时注销
7.避免使用枚举Enum(好多时候用枚举就图个好看)
8.使用更加轻量的数据结构

考虑使用ArrayMap/SpareseArray而不是传统的HashMap等数据结构。因为HashMap需要一个额外的实例对象来记录Mapping的操作。

9.如果没有必要,就不要用抽象类

因为抽象类这些一般都没有正经的事做。


三、页面上

1.优化布局层次,减少内存开销
2.Activity方面的问题

1.Activity对静态变量的持有问题
2.页面回收时记得清空Handler消息队列
3.Activity Context被其他实例持有

3.webview的泄露

Android不同版本对webview产生有很大差异。
常用的办法:为webview新开一个进程,通过AIDL与主进程通信。(在需要的时候对webView进行销毁


四、系统

1.自定义堆内存大小
2.优化Delivk虚拟机的堆内存分配
3.申请大内存large heap

谨慎使用!这可能会影响整个系统的用户体验。

4.Services用完及时停止。

因为这货的优先级一般较高,系统一般不会吧Service所占用的RAM空间腾出来让给其他组件

5.谨慎使用多进程

多进程可以把应用中的部分组件运行在单独的进程当中,系统一般会给多进程分配更多的内存,
但是这会显著增加代码的逻辑复杂度,而且容易成为业界的毒瘤。(这个,,嘛,,

6.注意第三方libraries的应用

一般你是不会用到一个libraries的所有功能的,这就存在用内存去养那些你压根就不会用的对象


赤夜染尽 千樱散落 零时夜雨 无茵之音