我的应用程序中有很多位图。它们在应用程序启动时加载。在一项活动中,我有两个按钮可以更改语言,但是当我单击按钮时,我会再次开始加载图像。有时我会因内存不足而出错。我如何清理内存,当我点击按钮时我清理内存,然后加载位图?这有可能吗?现在我使用system.exit(0)
但我不想关闭所有应用程序。
3 回答
不久前,我在使用图形处理密集型应用程序时遇到了同样的问题,经过大量调试后,我发现位图对象没有自动正确释放。
您应该在不再需要它们时立即调用它们的回收方法来自行管理位图(例如 Activity.onStop 方法)。
编辑(2014 年 10 月 8 日):
Android 开发者文档最终包含对这些位图内存问题的清晰解释。与此同时,有些事情已经变得更好,但我们通常仍然需要处理旧的 Android 版本,这使得位图内存管理变得困难。
以下是关键点:
从 Android 2.3.3(API 级别 10)及更低版本开始
- 像素数据存储在本机内存中...
- ...而不是在 Dalvik 堆内存中
- 像素数据以不可预知的方式释放
当您已经用位图(或其他大对象)耗尽了 Dalvik 堆内存限制并尝试加载另一个位图时,就会出现问题。即使您不再对旧位图对象持有任何引用,也不能保证在分配新位图对象之前这些位图得到垃圾收集。因此,您可以随机达到极限并获得OutOfMemoryError
.
因此,自己管理位图对象很重要。当您使用完一个位图后,您应该recycle()
在加载另一个位图之前调用它的方法。
从 Android 3.0(API 级别 11)开始
- 像素数据与位图对象一起存储在 Dalvik 堆上
在这里,Dalvik 的内存管理器可以看到剩余的内存量,并且可以完全控制回收内存。
管理位图
在这两种情况下(较旧的 Android 版本和较新的 Android 版本),您可能需要管理位图对象以避免:
- 重复加载同一张图片(优化问题)
- 内存不足(稳定性问题)
Android 开发人员文档包含有关如何使用最近最少使用的缓存 (LruCache)缓存和重用已加载的位图对象的详细信息。
不要打电话System.exit(0)
,因为它会终止你的 JVM。bitmap.recycle()
使用完后调用每个位图。这将释放位图获取的本机内存。此外,将位图引用设置为 null 将使 GC 在下次运行时收集它。
recycle
如果未从您的数据结构中引用未使用的位图并正确调用,您将不会收到 OutOfMemory 异常。一旦你确保了这一点,自动垃圾收集器就会开始可靠地为你服务,你不需要告诉它什么时候释放东西。
注意程序中的任何静态变量,尤其是集合或复杂结构。如果在任何地方添加了位图,请确保再次将其从那里删除。