我一直在构建一款可以加载,缩放和显示位图的Android游戏。每当我开始加载一批位图时,我的LG Nexus 4游戏的内存配置文件就会突然爆发。然后,当我开始与游戏进行交互(触摸屏幕以便走路等)时,内存消耗会急剧下降,然后随着磁贴背景滚动(图像在屏幕上掉落时卸载图像)而定期提升和下降少量
我最近在游戏中的某个特定位置添加了更多位图,它一直带到550 MB,然后因内存不足而崩溃。
我的艺术资产总量不到13 MB,我从来没有同时装满它们。为什么我的游戏在某些点消耗大量内存?
这是我的位图加载代码:
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();
}
}
答案 0 :(得分:2)
png或jpg文件的大小不是内存中的大小。 PNG和JPG是压缩的。在内存中位图是未压缩的。对于标准ARGB格式,这意味着它在内存中每像素需要4个字节,或者总共4 *宽*高度字节(加上少量开销,但与图像数据相比可以忽略)。因此,他们在磁盘上只有13 MB的事实并不意味着它不是内存中的几倍。
其次,Java是一种垃圾收集语言。这意味着在GC运行并实际收集内存之前,所使用的内存量不会减少。调用回收不会这样做,它只是释放对它的引用,以便GC可以在下次运行时释放它。这使得它成为一件好事,但在GC实际决定运行之前,你会看到尖峰。
至于您的实际代码 - 您的缩放效率低下。它创建了2个位图对象的缩放和非缩放副本。您应该只创建1.您可以使用可以传递给Bitmap工厂的BitmapFactory.Options来缩放它。
除此之外,在我发布的代码中没有看到任何内容,但这并不代表其他地方没有其他问题。