将largeHeap设置为true有哪些优点?

168

我的应用程序有大量的类和许多库被包含在内。由于出现了内存问题,我正在设置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>

我必须问这是一个好的实践吗? 请提供使用它的优缺点(利与弊)。


如果您的应用程序需要大量内存,比如游戏、3D 模型等。 - J.K
55
50个班级并不算多。 - Chris Hayes
https://developer.android.com/training/articles/memory.html - J.K
如果您在应用程序中使用了某些服务或其他应用程序,这些应用程序会消耗内存,那么您的应用程序将面临内存问题,例如相机是开发人员在使用应用程序时最常见的问题,或者如果您有很多变量正在消耗内存,静态变量也可能是其中的原因。 - Aditi
6
类的数量并不重要。通常需要大量内存的是位图。请参阅“将缩小版本加载到内存中”了解更多信息。 - ToolmakerSteve
根据官方文档,方法很重要,类并不重要。如果应用程序包含总共64K个方法,则使用multidex enabled=true。 - Ali Akram
6个回答

149

我可能来晚了,但我还是想提供我的0.02美元建议。不要在此处使用 android:largeHeap="true"。以下是谷歌的解释:

然而,请求大堆内存的功能仅适用于少量可以证明需要消耗更多 RAM 的应用程序(例如大型照片编辑应用程序)。永远不要仅因为内存已用完而需要快速修复而请求大堆内存-只有在您确切地知道所有分配内存的位置和为什么必须保留内存时才应使用它。即使您确信您的应用程序可以证明需要大堆内存,也应尽可能避免请求它。使用额外的内存将越来越损害整体用户体验,因为垃圾收集将花费更长时间,在任务切换或执行其他常见操作时系统性能可能会变慢。

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

更新

在与 out of memory errors 作斗争之后,我认为在清单中添加此项以避免出现oom问题并不是一种罪过。 此外,正如@Milad在下面指出的那样,它不会影响应用程序的正常工作。

更新2

以下是处理 out of memory errors 的几个提示:

1) 使用Android提供的回调函数onLowMemoryonTrimMemory(int),并清除缓存图片(如Picasso、Glide、Fresco等)。你可以在这里这里了解更多信息。
2) 压缩你的文件(图片、PDF)
3) 阅读有关如何更高效地处理位图的信息,点击这里
4) 在发布前定期使用Lint工具,以确保代码简洁而不臃肿。


1
为什么你说“它不会影响应用程序的正常工作”?这个答案讨论了一些后果。在其他地方,我看到一些应用程序的largeHeap GC甚至测量出更糟糕的时间。 - ToolmakerSteve
@Mightian,我的应用程序包含许多图库,包括旋转木马作品,因此是否应该使用android:largeHeap="true"? - Anisha Pal Mohor

71

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

你能得到什么:

  • 显然,你会获得更大的堆空间,这意味着减少了OutOfMemoryError的风险。

你会失去什么:

  • 可能会丢失一些帧,导致可见的卡顿现象。更大的堆空间使垃圾回收时间变长。因为垃圾收集器基本上必须遍历您所有的活动对象。通常,垃圾回收暂停时间约为5毫秒,您可能认为几毫秒并不重要。但是每一毫秒都很重要。Android设备必须在每16毫秒更新其屏幕,而较长的GC时间可能会将帧处理时间推超过16毫秒的限制,从而导致可见的卡顿现象。

  • 同时切换应用程序也会变慢。 Android系统可能会杀死最近最少使用的进程的LRU缓存,但也会考虑哪些进程最耗费内存。因此,如果你使用更大的堆,当你的应用程序处于后台时,你的进程更可能被杀死,这意味着用户想要从其他应用切换到你的应用时可能需要更长的时间。此外,当您的应用程序需要更多内存时,其他后台进程也更可能被踢出。这意味着从您的应用程序切换到其他应用程序也需要更长的时间。

结论:

尽可能避免使用largeHeap选项。这可能会导致难以察觉的性能下降和糟糕的用户体验。


21

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

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

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

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

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

getMemoryClass()不限制您的堆大小,但它告诉您,如果您希望您的应用程序在运行的特定设备的限制范围内舒适地和兼容地运行,则应使用多少堆。

与之相比,maxMemory() 确实限制了堆的大小,因此通过增加其值,您可以获得额外的堆访问权限,而 largeHeap 也确实增加了该值。然而,增加的堆量仍然是有限的,并且该限制将是设备特定的,这意味着您的应用程序可用的堆量会因运行应用程序的设备的资源而异。因此,使用 largeHeap 不意味着您的应用程序可以肆无忌惮地在自助餐厅里进食。
您的应用程序可以通过调用方法 getLargeMemoryClass() 来发现在特定设备上使用 largeHeap 参数将提供多少内存。返回的值以兆字节为单位。
这篇早期文章包括对 largeHeap 参数的讨论,以及关于在几个特定的 Android 设备上使用和不使用它所提供的堆数量的许多示例: Detect application heap size in Android

我从未将此参数设置为true来部署我的任何应用程序。 但是,在我的一款应用程序中,有一些占用内存较多的代码用于编译一组优化相关的参数,仅在开发期间运行。我仅在开发期间添加largeHeap参数,以避免在运行此代码时出现内存不足错误。但在部署应用程序之前,我会删除该参数(和代码)。


2
放下所有的顾虑,像一只猪一样在自助餐厅里大快朵颐。 - Joshua Pinter

18

实际上,android:largeHeap是增加应用程序分配内存的工具。

使用此标志的需要没有明确的定义。如果您需要更多的内存 - Android 提供了一个工具来增加它。但是否需要使用取决于您自己。


4
是的,有一个清晰的定义,请参考此链接:https://developer.android.com/training/articles/memory.html - Mightian
3
@war_Hero - 可能那篇文章已经改动过了?里面没提到largeHeap。 - ToolmakerSteve

18
我有一个包含近50个类的应用程序。 我认为这不会造成太大问题。你遇到OutOfMemory错误的原因通常是在应用程序中加载了过多的图像或类似的情况。如果您不想使用大堆,您必须找到一种优化内存使用的方法。 您还可以使用图像加载库,例如PicassoUILGlide。它们都具有将图像缓存到内存和/或磁盘中的功能。

1
对于图像加载,我通常推荐使用Picaso或Universal Image Loader。 - Mightian
6
Glide比Picasso更好且更加优化。 - Damien Praca
1
@DamienPraca 我认为不会,至少在使用Picasso时正确使用标签(setTag(),pauseTag(),resumeTag())的情况下不会出现问题。 - Ruslan Berozov

4

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

大多数应用程序不需要这样做,而应该专注于减少其总体内存使用以提高性能。启用此功能也不能保证可用内存固定增加,因为某些设备受其总可用内存的限制。


这是关于android:largeHeap的描述,来源于https://developer.android.com/guide/topics/manifest/application-element.html#largeHeap。 - pretorh

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