8

我正在开发一款安卓游戏。当我尝试使用 3 张图片作为背景时,问题就开始了。图片大小为 1280x720 像素,大小为 100kb。图像真的不是那么大,所以我有点困惑为什么它们会导致内存问题。

注意:屏幕分辨率为 800x400,因此我无法按照 android 开发人员的 建议图像大小调整为 2它工作正常。

我分析了 DDMS 中的内存,奇怪的是我发现堆只有 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 张图片作为背景。我们现在将在垂直方向调整它们的大小,但在水平方向我们仍然需要它们原样。所以图像仍将在 100x720 像素左右。我们需要 3 张图像的问题是,我们可以分别绘制它们并获得图层效果(我们可以在 2 张图像之间绘制一些东西)。用尽可能少的内存来实现这一点以获得理想效果的最佳方法是什么?

背景: 背景 中间: 中间 前景 前景

注意:这只是静态背景,动画会在它们周围和它们之间发生。

4

1 回答 1

4

我不确定你从哪里得到一个 1280 x 720 像素的位图是 100KB。真的是几兆。以字节为单位,它是 1280 * 720 * 但是每个像素有很多字节,通常是 4 个用于具有透明度的图像,或 2 个用于不具有透明度的图像。手机要加载的数据量很大。也许您引用的是压缩图像格式版本(例如 PNG)的大小。

处理内存使用问题的一些技巧:

如果您没有任何透明度,请在您的工厂使用 Bitmap.Config.RGB_565 输入格式。与 ARGB_8888 相比,这节省了空间。

在 AndroidManifest.xml 中的应用程序元素上将 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 之外分配了内存。

请注意,当您读取位图时,您实际上可以检查您需要它的大小是否是小于其大小的整数除数,然后指定工厂在加载时应跳过像素。这有助于较小分辨率的设备,这些设备具有相应较小的内存限制。

如果您不单独移动这些背景图像,则将它们全部绘制到一个位图中并使用它而不是一次使用三个。

于 2012-10-27T23:35:46.327 回答