【Android问题及其解决】又见图片导致的OOM

来源:互联网 发布:《java并发编程实战》 编辑:程序博客网 时间:2024/04/28 02:24

又见图片导致的OOM

发生环境

1.在一个Activity中,多个View(Layout)进行来回的切换,使用一个Stack来作为页面栈,对view进行入栈(打开新页面,这时总是new一个View出来)和返回操作(出栈)。 2.每个view基本都继承了RelativeLayout,并在其xml布局中都添加了数目不少的自定义View控件(基本注册登录流程中的控件,像TextView、带下拉框的EditView,自定义Button、各种图片素材等)。 3.工程本身所占内存不少。 4.有多个Activity,报错的这部分在一个单独的Activity中(简称为A)

重现路径

在A中,多次点击跳转按钮,来回切换View,重复几次之后,应用重启。

崩溃现象

首先,Devices中,模拟器进程几乎一下子减少了一半,之后再进行页面跳转操作,就会发生应用崩溃后再重启的现象

Logcat

在日志中,首先是有OOM的提示,出来一堆指示当前进程的内存占用情况,之后是好多进程逐个开始crash掉,同时出现的还有多个Service重启(包括系统Service和应用中的Service),最后当前Activity died掉。

解决方案

由于这个现象实在我进行ui适配之后发生的,所以基本可以判断,不是代码的问题,应该是添加了ui素材导致的。大概看了一下,修改的部分主要是添加了图片,修改了字体颜色、字体、背景色、和背景(主要是用xml写的)。所以,基本确认是由于图片的原因导致内存溢出。

如何解决呢?我在网上找到这篇关于android 使用bitmap的OOM心得和解决方案 博客作为参考,根据我的实际情况,做出如下的解决。

1.由于oom导致根本原因是图片占据了大量内存,直接原因是View频繁的创建,所以,这些View都需要实现这样的接口

interface IPageLifeCycle{    //应当在实例化之后,放置于viewGroup之前被调用    public void onForenground();    //应当在销毁之前,从当前显示的ViewGroup中移除时调用    public void onBackground();    //应当在当前对象不需要存在,置null时调用    public void onRemove();}

2.在自定义View中,也使用了数量不少的图片,以及自定义了一些以reference作为参数类型的自定义属性,用来存放drawable对象,所以这些图片也许需要在不使用时进行必要的释放。实现如下接口

interface IPageLifeCycle{    //释放内存    public void releaseMemory();}

3.在A中,回退页面时,当stack pop出来View之后,需要调用

(IPageLifeCycle)view.public void onBackground();(IPageLifeCycle)view.public void onRemove();view = null;

4.在自定义的View控件中实现 public void releaseMemory(){ //备注中的方法 }

4.在View的onRemove()方法中,释放本身的图片资源和其所有自定义控件的内存。 public void onRemove(){ (IPageLifeCycle).releaseMemory(); //备注中的方法 System.gc(); }

这样,每次pop了view,都会使得垃圾回收机制回收掉无用的、占据大量内存的资源。

备注

无论你是在xml中布局使用了:

android:background ,

还是在java代码中调用了:

setBackground(background);

setBackgroundDrawable(background)

setBackgroundResource(resid)的方式去设置了背景图片.

使用的时候,请调用一下对应的方法:

setBackgroundResource和android:background→setBackgroundResource(0);

setBackgroundDrawable(background)→ setBackgroundDrawable(null)

setBackground(background) → setBackground(null)

0 0