Android应用程序的内存消耗超过所有位图的总和
我一直在开发一款Android游戏,可以加载、缩放和显示位图。每当我开始加载一批位图时,我的LG Nexus 4上游戏的内存配置文件就会猛增。然后,当我开始与游戏交互时(触摸屏幕行走等),内存消耗会急剧下降,然后随着背景的滚动,有规律地增加和减少少量内存(图像从屏幕上卸载) 我最近在游戏中的某个特定点添加了更多位图,它一直占用我550 MB的内存,然后由于内存不足而崩溃 我的艺术资产总计不到13MB,而且我从未同时加载所有这些资产。为什么我的游戏在某些时候会消耗大量内存 这是我的位图加载代码:Android应用程序的内存消耗超过所有位图的总和,android,android-bitmap,Android,Android Bitmap,我一直在开发一款Android游戏,可以加载、缩放和显示位图。每当我开始加载一批位图时,我的LG Nexus 4上游戏的内存配置文件就会猛增。然后,当我开始与游戏交互时(触摸屏幕行走等),内存消耗会急剧下降,然后随着背景的滚动,有规律地增加和减少少量内存(图像从屏幕上卸载) 我最近在游戏中的某个特定点添加了更多位图,它一直占用我550 MB的内存,然后由于内存不足而崩溃 我的艺术资产总计不到13MB,而且我从未同时加载所有这些资产。为什么我的游戏在某些时候会消耗大量内存 这是我的位图加载代码:
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();
}
}
png或jpg文件的大小不是内存中的大小。PNG和JPG是压缩的。内存中的位图是未压缩的。对于标准ARGB格式,这意味着内存中每个像素需要4个字节,或者总共需要4个*宽度*高度字节(加上少量开销,但与图像数据相比可以忽略)。因此,磁盘上只有13MB的容量并不意味着内存中的容量不是13MB的几倍 其次,Java是一种垃圾收集语言。这意味着在GC运行并实际收集内存之前,使用的内存量不会减少。调用recycle并不能做到这一点,它只是释放对它的引用,以便GC可以在下次运行时释放它。这使它成为一件好事,但在GC真正决定运行之前,您将看到峰值 至于您的实际代码,您的扩展效率很低。它创建位图对象的2个副本-缩放和未缩放。您应该只创建1。您可以使用位图工厂对其进行缩放。您可以将选项传递给位图工厂
除此之外,我在发布的代码中没有看到任何内容,但这并不意味着其他地方没有其他问题。png或jpg文件的大小不是内存中的大小。PNG和JPG是压缩的。内存中的位图是未压缩的。对于标准ARGB格式,这意味着内存中每个像素需要4个字节,或者总共需要4个*宽度*高度字节(加上少量开销,但与图像数据相比可以忽略)。因此,磁盘上只有13MB的容量并不意味着内存中的容量不是13MB的几倍 其次,Java是一种垃圾收集语言。这意味着在GC运行并实际收集内存之前,使用的内存量不会减少。调用recycle并不能做到这一点,它只是释放对它的引用,以便GC可以在下次运行时释放它。这使它成为一件好事,但在GC真正决定运行之前,您将看到峰值 至于您的实际代码,您的扩展效率很低。它创建位图对象的2个副本-缩放和未缩放。您应该只创建1。您可以使用位图工厂对其进行缩放。您可以将选项传递给位图工厂
除此之外,我在发布的代码中没有看到任何内容,但这并不意味着其他地方没有其他问题。感谢您的快速回答。你能分享一下创建一个位图的语法吗?或链接?可在上找到缩小比例。扩大规模应该是类似的。请注意,虽然它调用decode两次,但第一次它只解码头,这非常快,几乎不需要内存(第一次是获取文件中位图的大小)。感谢您的帮助!谢谢你的快速回答。你能分享一下创建一个位图的语法吗?或链接?可在上找到缩小比例。扩大规模应该是类似的。请注意,虽然它调用decode两次,但第一次它只解码头,这非常快,几乎不需要内存(第一次是获取文件中位图的大小)。感谢您的帮助!