6

在我的应用程序中,我使用的是简单的画廊和封面流,我在封面流中单击的图像上有我的封面流图像画廊,我被重定向到内容全屏画廊的下一个活动,我什至可以滚动我的全屏画廊;但是当我在我的应用程序中放置更多图像或高分辨率图像时,由于位图大小超过 VM 预算,它会被强制关闭

所以我想在每次完成封面流程和画廊时清除堆内存,这样我就可以在我的应用程序中加载任何数量或任何分辨率的图像,所以如果有人可以帮助我......如何每次清除/清空堆内存我在我的代码中动态完成我的活动?我已经尝试过回收和 System.gc 方法

4

1 回答 1

31

你不能“清除堆”。当您的对象不再被引用时,VM 将自动执行此操作。

话虽如此,位图在 android 中是一件困难的事情。内存有限,当图像被解码为位图时,它会占用比压缩图像格式本身更多的内存。

您的解决方案没有简单的答案。即使你做的一切都正确,你也可能只是内存不足。话虽如此,这里有一些提示:

  1. 使用Bitmap.release(). 位图的特殊之处在于它们分配在本机堆栈(与 VM 相对)堆上。javadocs有点模糊,说你通常不需要调用它,但根据我的经验,你已经完成了支持位图的内存的虚拟机“线索”很重要。编辑:从 Android 3.0(API 级别 11)开始,像素数据与关联的位图一起存储在 Dalvik 堆中。

  2. 将位图加载到内存中缩放。这是有关该主题的博客文章。在某些设备上,您只能获得 24MB 堆,而高分辨率图像在加载到位图对象时可能会耗尽所有这些。没有办法解决这个问题,所以你必须按比例加载它。

  3. 不要System.gc()像另一个答案所说的那样打电话。构建 GC 算法的人比你我聪明;他们知道自己在做什么。当有可以通过 GC 释放的内存时,您将永远不会获得 OOME - GC 将始终在给您 OOME 之前运行。

  4. 这一点很明显,但请确保在不再需要位图时不要持有对位图的引用。

  5. 最后,这很糟糕,Android 不做堆压缩。这是我前段时间发布的一个SO问题,没有令人满意的答案。简而言之,Android 永远不会压缩堆,因此当您的应用程序不断为位图分配大块甚至中等大小的块时,您最终会遇到这样一种情况:虽然您没有内存不足,但没有足够大的连续为您分配的内存块,您将获得 OOME。正如我在问题中所写的那样,解决此问题的唯一方法是在用户退出时终止应用程序的进程。这使得下次启动速度变慢,但它保证了一个全新的堆。不要误会我的意思,我不可能相信这是正确的做法,但没有人想出更好的解决方案。

于 2012-03-21T05:30:25.363 回答