Android OOM产生原因及如何解决

尊重原创,转载请注明出处:Lee http://blog.csdn.net/hnulwt/article/details/44900761

OOM产生原因

OOM产生可能的原因是因为 1、加载大图片导致内存溢出 2、大量内存泄露
OOM产生的本质是什么呢?
Dalvik VM主要管理的内存 Java heap,由于手机设备的限制,一般一个应用使用的内存不能超过默认值 32M(不同设备略有差异,通过adb shell getprop | grep dalvik.vm.heapgrowthlimit命令查看),这也就是说,当在DVM上申请的堆内存大于默认阀值的时候,我们的应用就会抛出OutOfMemoryError
(其实我们会有这样的疑问,明明我的设备内存有1GB或者更大,但是这么一张图就OOM了?为什么会这样,这里有一篇可以让我们明白其中的原因:关于Bitmap分配在native heap还是dalvik heap上的说明。,第10点有说明)。

如何解决和避免OOM

1、解决大图片导致内存溢出

加载多图:

(1)使用软引用、弱引用,当堆内存不足的时候,就可以自动的释放这些缓存的Bitmap对象。

关于软引用的说明:
软引用(SoftReference)是用来设计object-cache的。他在JVM报告内存不足之前会清除所有的软引用,这样以来gc就有可能收集软可及的对象,可能解决内存不足的问题,避免内存溢出。什么时候会被收集取决于gc的算法和gc运行时可用内存的大小。

关于弱应用的说明:看一个例子更容易懂:

String test =new String("aaa");       
WeakReference<String> testWeak = new WeakReference<String>(test);       
test = null;       
System.out.println("before: "+ testWeak.get());       
System.gc();       
System.out.println("after: "+ testWeak.get()); 

结果:
before: aaa
after: null
如果你希望能随时取得某对象的信息,但又不想影响此对象的垃圾收集,那么你应该用 弱应用(Weak Reference)来记住此对象。

(2)使用过的图并且不再使用,可以调用Bitmap.recycle()加速回收。

if (null != bitmap && !bitmap.isRecycled()) {  
    bitmap.recycle();  
}  

(3)考虑使用文件缓存。

整个大图都需要加载:

得到bitmap之前先利用BitmapFactory.Options的inSampleSize的值得到压缩图片。
关键代码:

    // 第一次解析将inJustDecodeBounds设置为true,来获取图片大小 
    final BitmapFactory.Options options = new BitmapFactory.Options(); 
    options.inJustDecodeBounds = true; 
    BitmapFactory.decodeResource(res, resId, options); 
    // 调用上面定义的方法计算inSampleSize值, calculateInSampleSize方法自己写,这里不再赘述
    options.inSampleSize = calculateInSampleSize(options.outWidth, options.outHeight, reqWidth, reqHeight);

    options.inJustDecodeBounds = false; 
    Bitmap bmp = BitmapFactory.decodeResource(res, resId, options); 

只加载部分图片

可以考虑在API 10以后引进的BitmapRegionDecoder类,具体使用方式还未研究,源码注释(BitmapRegionDecoder is particularly useful when an original image is large and you only need parts of the image)。

2、解决内存泄露问题

解决该问题主要需要对Android系统各部分组件进行一些较深入了解,比如:
对Activity的生命周期进行了解以后,就应该避免对生命周期之外的引用。一个应用可能有多个Activity构成,这时候应该考虑使用Application类。(该问题主要是针对Activity中静态对象的控制)
尽量不要由于各种复杂的引用导致GC不能及时的甚至永远不能回收某块内存。

以上是我对OOM问题的一些解决方案,如果大家还有其他很好的方式恳请提出来,共同提升。

你可能感兴趣的:(Android)