“android:largeHeap = true”惯例是什么?

17
我正在编写一个图库应用程序,但是一直遇到内存不足错误。我缓存了所有的图片,但当我尝试 非常快地 切换图片时,问题就会发生。我认为应用程序分配内存的速度比垃圾回收器释放内存的速度快(因为当我慢慢切换图片时,没有出现崩溃)。
在苦恼了几天后,我最终决定在清单文件中设置largeHeap。设置之后,我的应用程序无论我多快地切换图片都不会崩溃。
现在,我想知道使用largeHeap设置是否有任何规范或通用指南,因为如果例如笔记应用程序使用largeHeap,可能并没有太多意义。一般来说,哪些应用程序是largeHeap设置的好候选?
谢谢

顺便说一句,如果你确定不再使用位图,请立即调用bitmap.recycle();,那么该位图的大部分内存将立即被释放。(当GC处理时,只剩下一个微小的对象。) - ToolmakerSteve
2个回答

23
一般来说,哪些应用程序是大堆设置的好选择?那些你可以向用户证明为什么要强制将他们的其他应用程序退出内存,以给你超大的堆空间的应用程序。
个人而言,“图像库应用程序”不符合资格。AutoCAD、视频编辑器等应用程序将符合资格。
关于您的内存管理问题,请确保在API Level 11+上运行时,在BitmapOptions上使用inBitmap,以回收现有缓冲区,而不是进行垃圾回收。特别是对于图像库,您可能有很多相当一致的缩略图大小,回收现有缓冲区将是一个巨大的优势。这可以帮助整体内存消耗(即,您真正用完了内存)和内存碎片化(即,您获得了OutOfMemoryError,但没有足够大的单个块来分配您的空间,由于Android的非紧凑垃圾回收器)。

您可能还考虑查看现有的图片缓存实现,比如Picasso提供的实现,看看是否有一些技巧可以学习(或者可能只是重复使用)。


谢谢你的回答!有一个问题: 我正在开发一个画廊应用,但我已经在使用 Picasso ,仍然遇到 OutOfMemoryError 的问题。你认为最好的做法是什么?使用 'largeHeap=true' 可以解决这个问题;除了这个快速解决方案,你认为还有其他我可以做的事情吗? - Karim
3
@Cookiki: "你认为最好做什么?" --弄清楚你真正的问题是什么。 你是否有内存泄漏? 是否可以重复使用Bitmap对象等等。 - CommonsWare

3
首先,请确保您不会加载比必要更大的位图:
加载经过缩放的版本到内存中
然后,在尝试使用 largeHeap 之前,尝试快速释放内存:
如果您在确定不再使用位图时立即调用 bitmap.recycle();,那么该位图的大部分内存将被立即释放。(当 GC 处理完后,只剩下一个微小的对象。)
在较新的 Android 版本中,有替代方法(而非 recycle)可能更有效:
管理位图内存 个人而言,我仍经常使用 recycle,特别是如果我可能会加载不同大小的图像,因此无法重复使用现有的图像。此外,当切换到另一个片段或活动时,我发现将旧媒体“卸载”与新媒体“加载”分开编码更容易实现:
在离开旧片段时,我将所有旧位图进行回收(然后,如果可以从静态字段访问,则设置为 null)。
是否使用 largeHeap 的经验法则是,在尝试其他方式减少内存使用后再考虑它。
编写应用程序时,请确保您可以将其关闭并仍然运行。
例如,监视内存使用情况,如果内存紧张,则加载“经过缩放的”位图。用户是否真的会注意到给定图像不符合其设备的“视网膜”分辨率?
或者,如果它是旧的、较慢的设备,那么大堆栈是否会使你的应用程序感觉迟钝 / 卡顿?如果是这样,您可以进一步降低分辨率,或者一次 只显示较少的位图
让您的应用程序在所有情况下工作,不需要使用 largeHeap [通过上述技术]。注意:您可以通过在全局字段中分配一些“虚拟”位图并保持对它们的引用(以便它们不会被释放)来“强制测试”在内存紧张的情况下运行。 现在,您能够评估影响您的应用程序的权衡:

当你打开 largeHeap 时,大量使用你的应用程序 - 有没有地方现在变得“更加缓慢”,或者动画“卡顿”或其他似乎不太流畅的情况?一定要在至少一个旧设备和一个高分辨率设备上进行测试。 可能会出现长时间GC(垃圾回收)时间,这是由于较大的堆。

或者你可能会得出结论,largeHeap 对你来说效果很好,现在你可以自信地说它是你的最佳选择。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接