在我的应用程序中,我使用的是简单的图库和封面流 我在封面流程中点击了我的封面图像库我被重定向到内容全屏画廊的下一个活动,我甚至可以滚动我的全屏画廊; 但是当我在我的应用程序中放入更多图像或高分辨率图像时,由于位图大小超过VM预算而被强制关闭
因此我想在每次完成封面流程和图库时清除堆内存,以便我可以在我的应用中加载任何数量或任何分辨率的图像 所以,如果任何人可以帮助我... 每当我在代码中动态完成活动时,如何清除/清空堆内存? 我已经尝试过循环和System.gc方法
答案 0 :(得分:31)
你不能“清除堆”。当您的对象不再被引用时,VM将自动执行此操作。
话虽这么说,位图在android中是一件很难的事。内存有限,当图像被解码为位图时,它会占用比压缩图像格式本身更多的内存。
您的解决方案没有简单的答案。即使你正确地做了一切,你可能只是内存不足。话虽如此,这里有一些提示:
使用Bitmap.release()
。位图的特殊之处在于它们是在本机堆栈(而不是VM)堆上分配的。 javadocs有点模糊,说你通常不需要调用它,但根据我的经验,这对VM的“线索”是你完成了支持位图的内存是很重要的。 编辑:从Android 3.0(API级别11)开始,像素数据与相关位图一起存储在Dalvik堆上。
将位图加载到内存缩放。这是关于该主题的blog post。在某些设备上只能获得24MB的堆,而高分辨率的图像在加载到位图对象时会耗尽所有这些。没有办法,所以你必须加载缩放。
请不要拨打System.gc()
作为另一个答案说。构建GC算法的人比你和我聪明;他们知道自己在做什么。当有可以通过GC释放的内存时,你永远不会得到OOME - GC会在给你一个OOME之前一直运行。
这个显而易见,但请确保在不再需要位图时不要引用位图。
最后,这个很糟糕,Android不做堆压缩。这是我前一段时间发布的SO question,没有令人满意的答案。简而言之,Android从不压缩堆,因此当您的应用程序不断为位图分配大块甚至中等大小的块时,最终会出现这样的情况,即在您没有内存不足的情况下,没有足够大的连续点你分配的内存块,你得到OOME。正如我在我的问题中写的那样,唯一的方式是在用户退出时杀死应用程序的进程。这使得下次启动变慢,但它保证了一个全新的堆。不要误解我的意思,我不可能相信这是正确的做法,但没有人能提出更好的解决方案。