你不能“清除堆”。当您的对象不再被引用时,VM 将自动执行此操作。
话虽如此,位图在 android 中是一件困难的事情。内存有限,当图像被解码为位图时,它会占用比压缩图像格式本身更多的内存。
您的解决方案没有简单的答案。即使你做的一切都正确,你也可能只是内存不足。话虽如此,这里有一些提示:
使用Bitmap.release()
. 位图的特殊之处在于它们分配在本机堆栈(与 VM 相对)堆上。javadocs有点模糊,说你通常不需要调用它,但根据我的经验,你已经完成了支持位图的内存的虚拟机“线索”很重要。编辑:从 Android 3.0(API 级别 11)开始,像素数据与关联的位图一起存储在 Dalvik 堆中。
将位图加载到内存中缩放。这是有关该主题的博客文章。在某些设备上,您只能获得 24MB 堆,而高分辨率图像在加载到位图对象时可能会耗尽所有这些。没有办法解决这个问题,所以你必须按比例加载它。
不要System.gc()
像另一个答案所说的那样打电话。构建 GC 算法的人比你我聪明;他们知道自己在做什么。当有可以通过 GC 释放的内存时,您将永远不会获得 OOME - GC 将始终在给您 OOME 之前运行。
这一点很明显,但请确保在不再需要位图时不要持有对位图的引用。
最后,这很糟糕,Android 不做堆压缩。这是我前段时间发布的一个SO问题,没有令人满意的答案。简而言之,Android 永远不会压缩堆,因此当您的应用程序不断为位图分配大块甚至中等大小的块时,您最终会遇到这样一种情况:虽然您没有内存不足,但没有足够大的连续为您分配的内存块,您将获得 OOME。正如我在问题中所写的那样,解决此问题的唯一方法是在用户退出时终止应用程序的进程。这使得下次启动速度变慢,但它保证了一个全新的堆。不要误会我的意思,我不可能相信这是正确的做法,但没有人想出更好的解决方案。