Android OOM问题终极解决方案

     大家在安卓开发的过程中使用Bitmap,尤其是当程序中包含大量图片的时候或多或少会遇到OOM(Bitmap: Out Of Memory),遇到这个问题是非常痛苦的,在这里给大家分享一下我自己结合网络上寻找的各种方案,以及自己的研究总结出来的解决方案。

     首先大家要知道OOM为什么会出现,通过上网查资料明白了是由于使用了 BitmapFactory.decodeFile(filePath) 这个方法导致的,这个方法通过Google提供的sdk看代码是将整个文件直接读取的所以占用资源比较大,所以找到的所有的解决方案一般都是直接调用BitmapFactory的底层decode方法,代码如下:

BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inPreferredConfig = Bitmap.Config.ARGB_8888;
        //  A  R  G  B
        //透明度 红色 绿色 蓝色
        //Bitmap.Config ARGB_4444 16 每个像素 占四位   
        //Bitmap.Config ARGB_8888 32 每个像素 占八位  
        //Bitmap.Config RGB_565 16 R占5位 G占6位 B占5位 没有透明度(A)
opt.inPurgeable = true;
opt.inInputShareable = true;
// 获取资源图片
File imageFile = new File(filePath);
FileInputStream fis = null;
try
{
    fis = new FileInputStream(imageFile);
}
catch (FileNotFoundException e)
{
    // TODO Auto-generated catch block
    e.printStackTrace();
}
Bitmap bm = null;
if (fis != null)
{
    try
    {
        bm = BitmapFactory.decodeFileDescriptor(fis.getFD(), null, opt);
    }
    catch (IOException e1)
    {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
    finally
    {
        try
        {
            fis.close();
        }
        catch (IOException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

对于Bitmap.Config的选择大家可以根据自己的实际情况进行选择,我的程序中使用的是Bitmap.Config.ARGB_8888,虽然经过他的处理图片占用的内存相对而言小了不少,但是对比其他的方式来说这个参数占用的内存也已经比较大了,但是为了保证图片的质量还是选择了它。

     上面的内容就是在我自己查资料的过程中找到的大部分的解决方式,在开发前期这种的确是够用了,我也没有意识到这样处理会有什么其他的隐患或者有什么地方没有处理正确,但是到了后期由于客户端页面层数较多,图片也比较多这时候可恶的OOM又开始出现了,在节省内存方面实在找不到什么更好的方式了,偶然发现了一个问题,我的Bitmap创建了,使用完之后并没有将资源释放掉,所以多个页面的图片都是一直占用设备内存的,不知不觉OOM就出现了。想解决这个问题看了几个比较高深的帖子,他们提倡用堆栈分配内存来解决这个问题,看了半天也没有看明白,于是就使用了一个比较笨的方法,但是没想到效果出奇的好,从那时开始OOM就彻底离我远去了。我做的app由于页面有一些相同的处理,所以有一个页面的基类,使用最简单的方式我在这个基类中添加了

/**
* 存放Bitmap
*/
private List<Bitmap> bitmapList = new ArrayList<Bitmap>();

在我调用工具类的时候就将新获取的Bitmap放到这对应的页面中来,在上面方法上面就加了这一句话

if (bm != null)
{
    activity.getBitmapList().add(bm);
}

这样我就能将所有的Bitmap通过我的页面全部管理收集起来了,最后我选择了在页面销毁的时候来将该页面绑定的所有Bitmap未释放的资源全部释放

@Override
protected void onDestroy()
{
    for (Bitmap bitmap : this.getBitmapList())
    {
        if (!bitmap.isRecycled())
        {
            bitmap.recycle();
        }
    }
    super.onDestroy();
}

这样就大功告成了!

     虽然我这个方法将所有页面的Bitmap资源全部集中存储起来耗费的内存还是比较大但是对于基本的来说这样就够用了,如果有图片用到比较多的地方大家可以直接将定义个List转换为Array,检测数组满时依次进行释放替换。

Android OOM问题终极解决方案,,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。