将 large Heap 设置为 true 有哪些优点?

我有一个应用程序与大量的类,也包括许多库,我正在设置 android:largeHeap="true",因为我得到的内存问题,我的清单文件代码是附加。

<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="My Huge Application"
android:largeHeap="true"
android:logo="@drawable/logo"
android:screenOrientation="portrait"
android:theme="@style/AppTheme" >
</application>

我不得不问,这是个好的练习吗? 请提出使用它的优点和缺点(正面和反面)。

114897 次浏览

是否应该使用大型 Dalvik 堆创建应用程序的进程。这适用于为应用程序创建的所有进程。它只适用于加载到进程中的第一个应用程序; 如果使用共享用户 ID 允许多个应用程序使用一个进程,它们都必须始终如一地使用该选项,否则将产生不可预测的结果。

大多数应用程序不应该需要这个,而应该把重点放在减少总体内存使用上,以提高性能。启用此选项也不能保证可用内存的固定增长,因为有些设备受到其可用内存总量的约束。

实际上,大堆是增加应用程序分配内存的工具。

没有明确的定义需要使用这个标志。如果你需要更多的内存,Android 提供了一个增加内存的工具。但使用的必要性,你定义了自己。

我有一个几乎有50个类的应用程序

我觉得这没什么问题。出现 outOfMemory 错误的原因通常是在你的应用程序中加载了太多的图片或类似的东西。如果您不喜欢使用大堆,那么必须找到使用内存进行优化的方法。

还可以使用图像加载库,如 毕加索UIL滑行。它们都具有在内存和/或磁盘上进行映像缓存的特性。

现在开派对已经太晚了,但我还是愿意出0.02美元。
使用 android:largeHeap="true"并不是一个好主意,下面是来自谷歌的摘录,

但是,请求大型堆的能力仅适用于 一小组应用程序,可以证明需要消耗更多的内存(如 不要简单地请求一个大堆 因为你已经用完了内存,你需要一个快速修复ーー你应该这样做 只有当你确切地知道你所有的记忆都在哪里的时候才能使用它 以及为什么必须保留它。然而,即使你有信心 你的应用程序可以证明大堆,你应该避免要求它 使用额外的内存将会越来越多 对整体用户体验的损害,因为垃圾 收集将需要更长的时间和系统性能可能会较慢时 任务切换或执行其他常见操作。

这是文件的完整链接 Https://developer.android.com/training/articles/memory.html

更新

在使用 out of memory errors进行了艰苦的工作之后,我想说,将这个功能添加到清单中以避免 Oom 问题并不是一种罪过,就像@Milad 在下面指出的那样,它不会影响应用程序的正常工作

更新2

这里有一些 小贴士out of memory errors

1)使用这些回调机器人给出的 onLowMemoryonTrimMemory(int)和清除缓存的图像(毕加索,滑翔,壁画... 。)你可以阅读更多关于他们的 给你给你
2)压缩档案(图片,pdf)
3)在这里阅读如何更有效地处理位图
4)在生产推进前定期使用皮棉,以确保代码光滑 不笨重

我认为这是一个非常有效的问题,让我补充一些关于使用这个选项的优点和缺点的细节。

你得到的:

  • 显然,您将获得更大的堆,这意味着降低 OutOfMemoryError的风险。

返回文章页面你的损失:

  • 您可能会丢失一些帧,这可能会导致一个可见的挂起 。堆越大,垃圾收集的时间就越长。因为垃圾收集器基本上必须遍历整个活动对象集。通常,垃圾收集暂停时间约为5毫秒,您可能认为几毫秒不是什么大问题。但每一毫秒都很重要。Android 设备必须每隔16毫秒更新一次屏幕,而 GC 时间的延长可能会使帧处理时间超过16毫秒,这可能会导致可见的延迟。

  • 此外,切换应用程序将变得更慢。Android 系统可能会从最近使用最少的进程开始杀死 LRU 缓存中的进程,但也会考虑哪些进程的内存密集程度最高。因此,如果你使用更大的堆,你的进程更有可能在后台处理时被终止,这意味着当用户想要从其他应用程序切换到你的应用程序时,它可能需要更长的时间。另外,当您的进程是前台的时候,其他后台进程更有可能被踢出,因为您的应用程序需要更大的内存。这意味着从你的应用程序切换到其他应用程序也需要更长的时间。

结论:

尽可能避免使用 largeHeap选项。它可能会让你难以察觉的性能下降和糟糕的用户体验付出代价。

如果您使用(并保留)大量的内存,那么是的,您可以并且应该使用 android:largeHeap="true"。但是如果你使用它,你应该准备好在其他应用出现在前台时将你的应用从内存中清除。

所谓“做好准备”,我的意思是您应该针对这种可能性进行设计,以便尽可能高效地编写 onStop()onResume()方法,同时确保所有相关状态的保存和恢复方式向用户呈现无缝外观。

与此参数相关的方法有三种: maxMemory()getMemoryClass()getLargeMemoryClass()

对于大多数设备,默认情况下 maxMemory()将表示与 getMemoryClass()相似的值,尽管后者以兆字节表示,而前者以字节表示。

当使用 largeHeap参数时,maxMemory()将增加到特定于设备的更高级别,而 getMemoryClass()将保持不变。

getMemoryClass()并不限制堆的大小,但是它会告诉你如果你想让你的应用程序在你运行的特定设备的限制范围内运行 很舒服和谐相处,你 应该使用的堆的大小。

相比之下,maxMemory()限制了堆的大小,因此您可以通过增加堆的值来获得对其他堆的访问,而 largeHeap确实增加了这个值。但是,增加的堆数量仍然是有限的,而且这个限制是特定于设备的,这意味着应用程序可用的堆数量会有所不同,这取决于运行应用程序的设备的资源。因此,使用 largeHeap并不意味着你的应用程序可以放弃所有的谨慎,在“吃到饱”的自助餐中寻找出路。

通过调用方法 getLargeMemoryClass(),应用程序可以通过使用 largeHeap参数确切地发现特定设备上有多少内存可用。返回的值以兆字节为单位。

这篇早期的文章包含了对 largeHeap参数的讨论,以及一些示例,说明在几个特定的 Android 设备上,使用和不使用堆的情况下,堆的数量是多少:

在 Android 中检测应用程序堆大小

我没有部署任何我自己的应用程序与此参数设置为真。然而,在我的一个应用程序中有一些内存密集型代码,用于编译一组仅在开发期间运行的与优化相关的参数。我只在开发期间添加 largeHeap参数,以避免在运行此代码时出现内存不足错误。但是我在部署应用程序之前删除了参数(和代码)。