浅谈andorid应用之OOM

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/angelsmiling/article/details/102706325

1. 前言

OOM(Out of Memory)即内存溢出,是因为应用所需要分配的内存超过系统对应用内存的阈值,而抛出的java.lang.OutOfMemoryError错误。

OOM的根本原因是开发者对内存使用不当造成的。内存使用不当一般指用内存之后,没有主动释放申请的内存,导致内存紧张,后面程序如果继续申请内存的话就有可能超出内存阈值,导致系统崩溃而异常退出。这个也通常被称为内存泄漏,内存泄漏最终会导致内存溢出

2. 内存阈值

为了整个Android系统的内存控制需要,Android系统为每个应用程序都设置了一个硬性的Dalvik Heap Size最大限制阈值,这个阈值在不同的设备上回因为RAM大小不同而有所差异。如果你的应用占用内存空间已经接近这个阈值,此时再尝试分配内存的话,很容易引起OutOfMemoryError的错误。所以开发者应该严格遵守使用内存之后应及时释放的原则。

3. 预防方法

主要是从三个方面入手:减小对象的内存占用,内存对象的重复利用,避免对象的内存泄漏。

3.1减小对象的内存占用

避免OOM的第一步就是要尽量减少新分配出来的对象占用内存的大小,尽量使用更加轻量级的对象

1.使用更加轻量的数据结构
使用ArrayMap/SparseArray替代HashMap等传统数据结构。
ArrayMap是Android系统专为移动操作系统编写的容器,在大多数情况下,比HashMap效率更高,占用内存更少。
SparseArray更加高效在于它们避免了对key和value的autobox自动装箱,并且避免了装箱后的解箱。

2.避免在Android里面使用Enum
Android官方说明”Enums often require more than twice as much memory as static constants. You should strictly avoid using enums on Android.“,所以应避免在Android里面使用枚举。

3.减小Bitmap对象的内存占用
Bitmap是一个极容易消耗内存的大胖子,减小创建处理的Bitmap的内存占用是很重要的,通常来说有下面2个措施:
inSampleSize:缩放比例,在把图片载入内存之前,我们需要先计算出一个合适的缩放比例,避免不必要的大图载入。
decode format:解码格式,选择ARGB_8888/RGB_565/ARGB_4444/ALPHA_8,存在很大差异。

4.使用更小的图片
对应资源图片,要特别留意这张图片是否存在可压缩的空间,是否可以使用一张更小的图片。尽量使用更小的图片不仅仅可以减少内存的使用,还可以避免出现大量的InflationException。

3.2 内存对象的重复利用

大多数对象的复用,最终实施的方案都是利用对象池技术,要么是在编写代码的时候显示的在程序里面去创建对象池,然后处理好复用的实现逻辑,要么就是利用系统框架既有的某些复用特性达到减少对象的重复创建,从而减少内存的分配与回收。

1.复用系统自带的资源
Android系统本身内置了许多的资源,如字符串、颜色、图片、动画、样式以及简单布局等,这些资源可以在应用程序中直接使用。这样做不仅仅可以减少应用程序的自身负重,减小APK的大小。但是要留意Android系统的版本差异性。

2.注意在ListView/GridView等出现大量重复子组件的视图里面对ConvertView的复用

3.Bitmap对象的复用
使用LRU机制来缓存处理好的Bitmap。

4.避免在onDraw方法里面执行对象的创建
类似onDraw等频繁调用的方法,一定需要注意避免在这里做创建对象的操作,因为它会迅速增加内存的使用,而且很容易引起频繁的GC,甚至是内存抖动。

5.StringBuilder
当代码中需要使用到大量的字符串拼接操作,就有必要考虑使用StringBuilder来代替频繁的”+“。

3.3 避免对象的内存泄漏

内存对象的泄漏,会导致一些不再使用的对象无法及时释放,这样一方面占用了宝贵的内存空间,很容易导致后续需要分配内存的时候,空闲空间不足而出现OOM。

1.注意Activity的泄漏
第一种情况是内部类引用导致Activity的泄漏,还有一种是Activity Context自身被引用而发生泄漏。

2.考虑使用Application Context而不是Activity Context
对于大部分非必须使用Activity Context的情况(Dialog的Context就必须是Activity Context),都可以考虑使用Application Context而不是Activity的Context,这样就可以避免不经意的Activity泄漏。

3.注意临时Bitmap对象的及时回收
临时创建的某个相对比较大的bitmap对象,在经过转换得到新的bitmap对象之后,应该尽快回收原始的bitmap,这样能够更快释放原始bitmap所占用的空间。

4.注意监听器的注销
在Android程序里面存在很多需要register和unregister的监听器,需要确保在合适的时候及时unregister那些监听器。

5.注意缓存容器中的对象泄漏
如果容器是静态或者全局的,那么对于里面存放的对象要及时remove。

6.注意WebView的泄漏
Android中WebView存在很大的兼容性问题,需要再合适的时机进行销毁。

7.注意Cursor对象是否及时关闭
对于数据库查询的Cursor,如果没有及时关闭就会造成泄漏。

猜你喜欢

转载自blog.csdn.net/angelsmiling/article/details/102706325
今日推荐