我正在开发一款Android游戏。当我尝试使用3张图像作为背景时问题就出现了。图像为1280x720px和100kb大。 图像真的不是那么大,所以我有点困惑为什么它们应该导致内存问题。
注意:屏幕分辨率为800x400,因此我无法按照因子2调整图像大小,因为suggested on android developer 注意:我正在使用HTC欲望手机(这里是崩溃来了),我也尝试过三星Galaxy S1和三星它的工作正常。
我已经分析了DDMS中的内存,奇怪的是我发现Heap只有3.5mb大。如果我检查rt.MaxMemory(),它说每个应用程序有大约25mb的空间。
我想到的是,堆没有足够快地“更新”以适应更大的照片/应用程序,所以它在加载图像之前崩溃,尽管它很小。有没有办法手动设置堆大小,或者至少告诉它放大?
以下是我加载图片的代码:
Bitmap floorFront = BitmapFactory.decodeResource(host.getResources(), R.drawable.floor1);
floorFront = Bitmap.createScaledBitmap(floorFront,host.realWidth,host.realHeight, true);
floorFront = Bitmap.createBitmap(floorFront, 0, host.realHeight/2, host.realWidth, host.realHeight/2);
host.addInstance(new Background(0,host.realHeight/2,host,floorFront,1));
Bitmap floorBack = BitmapFactory.decodeResource(host.getResources(), R.drawable.sand);
floorBack = Bitmap.createScaledBitmap(floorBack,host.realWidth,host.realHeight, true);
floorBack = Bitmap.createBitmap(floorBack, 0, host.realHeight/2, host.realWidth, host.realHeight/2);
host.addInstance(new Background(0,host.realHeight/2,host,floorBack,4));
Bitmap floorRock = BitmapFactory.decodeResource(host.getResources(), R.drawable.foreground);
floorRock = Bitmap.createScaledBitmap(floorRock,host.realWidth,host.realHeight, true);
floorRock = Bitmap.createBitmap(floorRock, 0, host.realHeight/2, host.realWidth, host.realHeight/2);
host.addInstance(new Background(0,host.realHeight/2,host,floorRock,0));
以下是LogCat的确切错误:
maxMemory:25165824
memoryClass:24
6144000-byte external allocation too large for tgis process.
Out of memory: Heap Size=4739KB, Allocated=2399KB, Bitmap Size=18668KB
VM won't let use allocate 6144000bytes
编辑: 现在您说有意义的是位图使用“原始”图像大小而不是压缩。经过一些研究后,似乎在Android 2.2和2.3位图上没有存储在堆中,因此在加载图像后堆不会增加。
我还有一个问题。我们使用这3张图片作为背景。我们现在将在垂直方向上调整它们的大小,但在水平方向上我们仍然需要它们。所以图像仍然是100x720px左右。我们需要3个图像的问题是,所以我们可以单独绘制它们并获得图层效果(我们可以在2个图像之间绘制一些东西)。实现这一目标的最佳方法是什么,以尽可能少的内存来获得理想的效果?
背景: 中间: 前景
注意:这只是静态背景,动画发生在它们周围和之间。
答案 0 :(得分:4)
我不知道你从哪里获得1280 x 720像素的位图是100KB。它实际上是几兆字节。以字节为单位,它是1280 * 720 *,但是每个像素有多个字节,对于具有透明度的图像通常为4,对于没有图像的图像通常为2。这是手机加载的大量数据。也许您引用的是压缩图像格式版本的大小,例如PNG。
处理内存使用问题的一些提示:
如果您没有透明度,请在工厂中使用Bitmap.Config.RGB_565输入格式。与ARGB_8888相比,这节省了空间。
在AndroidManifest.xml中的application元素上将largeHeap设置为true。
确保您的位图不会根据设备密度等级自动缩放。例如,将它们放在drawable-nodpi中,或者以编程方式禁用自动缩放,或者为多个可绘制文件夹中的每个密度类提供不同的位图。如果您的位图仅位于可绘制文件夹中,则它将在XHDPI设备上缩放2倍。
回收您未使用的位图,例如:
Bitmap floorFront = BitmapFactory.decodeResource(host.getResources(), R.drawable.floor1);
Bitmap floorFrontScaled = Bitmap.createScaledBitmap(floorFront,host.realWidth,host.realHeight, true);
floorFront.recycle();
floorFront = null;
Bitmap floorFrontCropped = Bitmap.createBitmap(floorFrontScaled, 0, host.realHeight/2, host.realWidth, host.realHeight/2);
host.addInstance(new Background(0,host.realHeight/2,host,floorFrontCropped,1));
您也可以手动运行System.gc()。系统应该在返回OutOfMemoryError之前为您执行此操作,但它不适用于Android中的位图,因为它们在Java之外分配了内存。
请注意,当您在Bitmap中读取时,您实际上可以检查您需要它的大小是否小于其大小的整数除数,然后指定工厂应在加载时跳过像素。这对较小分辨率的设备有帮助,这些设备具有相应较小的内存限制。
如果你没有单独移动这些背景图像,那么将它们全部绘制到一个位图并使用它而不是一次三个。