将 largeHeap 设置为 true 有啥好处?
Posted
技术标签:
【中文标题】将 largeHeap 设置为 true 有啥好处?【英文标题】:What are advantages of setting largeHeap to true?将 largeHeap 设置为 true 有什么好处? 【发布时间】:2015-02-08 09:42:37 【问题描述】:我有一个包含大量类和许多库的应用程序,我正在设置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>
我不得不问这是一个好习惯吗? 请提出使用它的优点和缺点(优点和缺点)。
【问题讨论】:
如果您的应用需要大内存,例如游戏 3dmodel 等 50节课也不算多。 developer.android.com/training/articles/memory.html 如果您在应用程序中使用某些服务或任何其他应用程序应用程序消耗内存,那么您的应用程序将出现内存问题,例如相机是开发人员在使用应用程序时最常见的问题,或者如果您有很多问题消耗内存的变量或静态变量也可能是原因。 类的数量并不重要。通常需要大量内存的是位图。请参阅“Load a Scaled Down Version into Memory”。 【参考方案1】:在这里聚会太晚了,但无论如何我都会提供我的 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 提供的这些回调 onLowMemory
, onTrimMemory(int)
并清除图像缓存(毕加索,滑翔,壁画......)您可以阅读更多关于他们的信息here 和 here
2) 压缩文件(图片、pdf)
3) 了解如何更有效地处理位图here
4) 在生产推送之前定期使用 lint 以确保代码流畅且
不笨重
【讨论】:
为什么说“不影响app正常工作”? This answer 讨论了一些后果。在其他地方,我看到在某些应用程序上测量 largeHeap GC 的时间更差。 @Mightian,我的应用确实包含很多图片库,包括轮播作品,所以使用 android:largeHeap="true" 应该是正版吗?【参考方案2】:我认为这是一个非常有效的问题,让我补充一些关于使用此选项的优缺点的细节。
你会得到什么:
显然,堆会更大,这意味着OutOfMemoryError
的风险会降低。
你会失去什么:
您可能会丢失一些帧,这可能会导致可见的卡顿。更大的堆使垃圾收集需要更长的时间。因为垃圾收集器基本上必须遍历您的整个活动对象集。通常,垃圾收集暂停时间约为 5ms,您可能认为几毫秒没什么大不了的。但每一毫秒都很重要。 Android 设备必须每 16 毫秒更新一次屏幕,较长的 GC 时间可能会使您的帧处理时间超过 16 毫秒的障碍,这可能会导致明显的卡顿。
切换应用程序也会变慢。 Android 系统可能会从最近最少使用的进程开始杀死 LRU 缓存中的进程,但也会考虑哪些进程最占用内存。因此,如果您使用更大的堆,您的进程在后台运行时更有可能被杀死,这意味着当用户想要从其他应用程序切换到您的应用程序时可能需要更长的时间。当您的进程处于前台时,其他后台进程也更有可能被踢出,因为您的应用程序需要更大的内存。这意味着从您的应用切换到其他应用也需要更长的时间。
结论:
尽可能避免使用largeHeap
选项。这可能会让您付出难以察觉的性能下降和糟糕的用户体验。
【讨论】:
【参考方案3】:其实android:largeHeap是增加你分配给应用内存的工具。
没有明确定义需要使用这个标志。如果您需要更多内存 - Android 为您提供了增加内存的工具。但是使用的必要性,你自己定义。
【讨论】:
是的,有明确的定义参考这个链接developer.android.com/training/articles/memory.html @war_Hero - 也许那篇文章改变了它的内容?里面没有提到 largeHeap。【参考方案4】:如果您必须使用(并保留)大量内存,那么是的,您可以并且应该使用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
参数,以避免在运行此代码时出现内存不足错误。但我在部署应用程序之前删除了参数(和代码)。
【讨论】:
“放弃所有谨慎,尽情享用自助餐” ?【参考方案5】:我有一个包含近 50 个类的应用
我认为这不会造成太大问题。你得到 outOfMemory 错误的原因通常是在你的应用程序中加载了太多的图像或类似的东西。如果您不喜欢使用大堆,则必须找到一种优化内存使用的方法。
您还可以使用图像加载库,例如 Picasso、UIL 或 Glide。它们都具有在内存和/或磁盘上缓存图像的功能。
【讨论】:
图片加载我一般推荐picaso或者通用图片加载器 Glide 比 Picasso 更好,优化了一些 @DamienPraca 我不这么认为,至少如果你在 Picasso 中正确使用标签(setTag()、pauseTag()、resumeTag())。【参考方案6】:您的应用程序的进程是否应该使用大型 Dalvik 堆创建。这适用于为应用程序创建的所有进程。它仅适用于加载到进程中的第一个应用程序;如果您使用共享用户 ID 来允许多个应用程序使用一个进程,则它们都必须一致地使用此选项,否则将产生不可预知的结果。
大多数应用不应该需要这个,而是应该专注于减少整体内存使用以提高性能。启用此功能也不能保证可用内存的固定增加,因为某些设备受到其总可用内存的限制。
【讨论】:
以上是关于将 largeHeap 设置为 true 有啥好处?的主要内容,如果未能解决你的问题,请参考以下文章
Android--hardwareAccelerated 硬件加速详解 android:largeHeap="true"