原因:系统为每一个应用程序分配了不同的内存上限,如果超过这个上限被视为内存泄露,从而被kill掉。
比如:
1.加载对象过大
2.相应资源过多,来不及加载。
解决办法们
oom这个真的不好权衡,下面这些注意事项好多是相互矛盾的,根据业务,各取所需吧。
而且一味的追求小内存开销,也不好。
毕竟,硬件本身的性能越来越强大,你不用,它也会老化。
一、图片
1.内存中加载图片直接在内存中做处理(如边界压缩)
2.减少Bitmap对象的内存占用
1.加载之前先计算出合适的缩放比例
2.选择合适的解码格式:ARGB_8888/RBG_565/ARGB_4444/ALPHA_8,内存在很大差异。
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的所有功能的,这就存在用内存去养那些你压根就不会用的对象
网友评论