Android应用中的内存消耗超过了所有位图的总和

时间:2016-03-04 23:21:32

标签: android android-bitmap

我一直在构建一款可以加载,缩放和显示位图的Android游戏。每当我开始加载一批位图时,我的LG Nexus 4游戏的内存配置文件就会突然爆发。然后,当我开始与游戏进行交互(触摸屏幕以便走路等)时,内存消耗会急剧下降,然后随着磁贴背景滚动(图像在屏幕上掉落时卸载图像)而定期提升和下降少量

我最近在游戏中的某个特定位置添加了更多位图,它一直带到550 MB,然后因内存不足而崩溃。

我的艺术资产总量不到13 MB,我从来没有同时装满它们。为什么我的游戏在某些点消耗大量内存?

enter image description here

这是我的位图加载代码:

public class BackgroundBitmapLoader implements Runnable {

    public GameView gameView;
    public BackgroundTile backgroundTile;
    public Bitmap bitmap;
    public int drawableID;
    public Context context;
    public int scaledWidth;
    public int scaledHeight;

    public BackgroundBitmapLoader(GameView gameView, BackgroundTile backgroundTile, Context context, int drawableID, int scaledWidth, int scaledHeight) {
        this.gameView = gameView;
        this.backgroundTile = backgroundTile;
        this.context = context;
        this.drawableID = drawableID;
        this.scaledHeight = scaledHeight;
        this.scaledWidth = scaledWidth;
    }

    public void run() {
        bitmap = BitmapFactory.decodeResource(context.getResources(), drawableID);
        bitmap = Bitmap.createScaledBitmap(bitmap, scaledWidth, scaledHeight, false);
        backgroundTile.setBitmap(bitmap);
        gameView.incrementLoadedBitmapCount();
    }
}

这是我用于在屏幕移出屏幕或不再需要时卸载位图的代码:

public class BitmapUnloader implements Runnable {

    Bitmap bitmap;

    public BitmapUnloader(Bitmap bitmap) {
        this.bitmap = bitmap;
    }

    public void run() {
        bitmap.recycle();
    }
}

1 个答案:

答案 0 :(得分:2)

png或jpg文件的大小不是内存中的大小。 PNG和JPG是压缩的。在内存中位图是未压缩的。对于标准ARGB格式,这意味着它在内存中每像素需要4个字节,或者总共4 *宽*高度字节(加上少量开销,但与图像数据相比可以忽略)。因此,他们在磁盘上只有13 MB的事实并不意味着它不是内存中的几倍。

其次,Java是一种垃圾收集语言。这意味着在GC运行并实际收集内存之前,所使用的内存量不会减少。调用回收不会这样做,它只是释放对它的引用,以便GC可以在下次运行时释放它。这使得它成为一件好事,但在GC实际决定运行之前,你会看到尖峰。

至于您的实际代码 - 您的缩放效率低下。它创建了2个位图对象的缩放和非缩放副本。您应该只创建1.您可以使用可以传递给Bitmap工厂的BitmapFactory.Options来缩放它。

除此之外,在我发布的代码中没有看到任何内容,但这并不代表其他地方没有其他问题。