Android分配变量时出现内存不足问题

5
所以我得到了这个:
'01-01 20:37:34.859: E/dalvikvm-heap(19921): Out of memory on a 6471856-byte allocation.'

当试图将一组变量分配到内存时。 我正在分配24个这样的变量:
mElements.add(new ShopElement(getResources(),R.drawable.shop_starter, b1X , b1Y,true,1,"red",true,5,checkLocked(0)));

并且其中之一:

bNumbers = new Bitmap[] {Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.h0)
        , 65,65, true),
        Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.h1)
        , 65,65, true),
        Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.h2)
        , 65,65, true),
        Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.h3)
        , 65,65, true),
        Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.h4)
        ,65,65,true),
        Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.h5)
        , 65,65, true),
        Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.h6)
        , 65,65, true),
        Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.h7)
        , 65,65, true),
        Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.h8)
        , 65,65, true),
        Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.h9)
        , 65,65, true),
        Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.time)
                , 50,50, true)};

在我创建的24个元素中,当我完成第16个时,它会在某些手机上崩溃。

我有一个Galaxy S2,它运行得很好,但是在S3和其他手机上会崩溃。

如需更多信息,请告诉我。

我之前搜索过这个错误,尝试了解决方案,并查看了“高效显示位图”文档,但似乎没有帮助。

让我困惑的是它在S2上可以运行,但在S3上却不行。难道S3不应该在所有方面都优于S2吗?

我正在使用全局的BitmapFactory.Options来绘制所有的位图,我将选项设置如下:

Global.opts = new BitmapFactory.Options();
    Global.opts.inDither=false;                     
    Global.opts.inPurgeable=true;                  
    Global.opts.inInputShareable=true;              
    Global.opts.inTempStorage=new byte[16 * 1024]; 

3
当然。你将这么多位图放入内存中了。尝试优化你的逻辑。 - Raptor
1
我的猜测是它崩溃的手机可用内存比没有崩溃的手机少。调整图像大小通常在内存方面非常昂贵,也许可以分块处理,以便垃圾回收有时间工作。 - Matthew
我在“分块处理”方面没有经验。这是否意味着我应该按帧分离分配组变量? - user773737
1
天哪!你真的要把6.5++ MB的图片加载到你的手持设备上吗?50K - 合理。1MB - 较大。6.5MB - 不可能!在我看来... - paulsm4
“ShopElement”是什么样子的?每个实例是否也创建了一个“bNumbers”数组?仅仅展示传入可绘制Id的构造函数并不能暗示该对象对该Id执行了什么操作。 - devunwired
显示剩余3条评论
3个回答

8
您正在尝试访问比您拥有的内存更多的内存。因此,解决方案是增加内存或仅使用可用内存。有三个建议来实现这一点。 1)如果您正在使用BitmapFactory.Options并且错误仍然存在,则表示您未针对给定图像正确配置它。请确保堆大小足够。
 BitmapFactory.Options opts=new BitmapFactory.Options();
        opts.inDither=false;                     //Disable Dithering mode
        opts.inSampleSize = 8;                    // scale image upto 1/8 of the original image.
        opts.inPurgeable=true;                   //Tell to gc that whether it needs free memory, the Bitmap can be cleared
        opts.inInputShareable=true;              //Which kind of reference will be used to recover the Bitmap data after being clear, when it will be used in the future
        opts.inTempStorage=new byte[16 * 1024]; //you can increase this value as per your need.

您可以通过增加inTempStorage大小或使用inSampleSize属性对图像进行抽样来解决该问题。关于抽样的更多信息,请参考此链接

尝试使用不同的选项,应该可以解决问题。

2)您还可以在manifest文件中使用android:largeHeap="true"属性来增加应用程序的整体堆大小,但这无法在任何早期版本的Honeycomb设备上工作。在2.3以下的设备上,您可以使用VMRuntime类。

3)如果您想以编程方式检测您的堆大小,并根据需要进行更改,则可以参考此链接


我编辑了问题,包括了我如何使用Options的示例。 我会尝试增加堆大小。 - user773737
那不起作用。每当我尝试应用“android:largeHeap =”true“”时,它只会给我一个红色的X并显示“找不到资源标识符”。 - user773737
包括“inSampleSize”似乎起作用了,但现在一切看起来都很糟糕。但它能工作,所以你明白我的意思。我将尝试调整示例大小和检测堆大小,并暂时动态调整它,直到我找到更好的方法来加载我的34个位图。 - user773737
同时,请使用尽可能小的位图。这样可以节省内存。更重要的是,您的应用程序应该运行得更快,并且更具有吸引力。在我看来。。 - paulsm4

2
错误信息明确表示您正在尝试使用更多内存。这直接指向图像大小。因此,您需要调整图像大小以使用更少的内存。可以用于此目的的选项之一是 BitmapFactory.Option 。或者手动调整图像大小,确保它满足所有需求。仅为解释事情而言,

堆大小是分配给应用程序执行的内存量。 Android应用程序的堆大小由设备RAM确定。 例如,如果设备具有179 MB的RAM,则Android应用程序将只获得18MB的堆大小。

在此处了解更多信息here。有关如何高效加载大型位图的详细信息,请单击here

我有一个Galaxy S2,它运行良好,但在S3和其他手机上会崩溃

请检查您提到的设备的RAM大小。

我正在使用 BitmapFactory.Option。 - user773737
尝试使用inSampleSize - Vinay
谢谢您建议inSampleSize。它有效,但我会把功劳归于CCMinds,因为他在他的答案中提到了它。希望你不介意。反正你已经有很多积分和奖章了。 - user773737

1
在Android内存管理中,每个应用程序都有一个可以使用的最大堆内存,一旦应用程序使用超过堆内存,Android操作系统将自动杀死该应用程序。因此,只有当您遇到"内存不足异常"时才会出现这种情况。
为了解决这个问题,您可以采用Android NDK概念。由于堆概念是针对SDK部分的。

i.e,

你可以使用NDK让应用程序使用超过300MB(如果可用)的RAM,但在SDK中无法实现。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接