有两种方法可以考虑您的短语“应用程序堆大小可用”:在触发严重错误之前,我的应用程序可以使用多少堆?和
有多少堆应我的应用程序使用,考虑到Android操作系统版本和用户设备硬件的限制?
有一种不同的方法来确定上述每一个。
关于上文项目1:maxMemory()
它可以被调用(例如,在您的主要活动中)onCreate()方法)如下:Runtime rt = Runtime.getRuntime();long maxMemory = rt.maxMemory();Log.v("onCreate", "maxMemory:" + Long.toString(maxMemory));
此方法告诉您总共有多少个字节你的应用程序是堆的允许利用。
关于上文项目2:getMemoryClass()
可按以下方式调用:ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);int memoryClass = am.getMemoryClass();Log.v("onCreate", "memoryClass:" + Integer.toString(memoryClass));
这个方法告诉你大约有多少兆字节堆你的应用程序应如果它想要适当地尊重当前设备的限制,以及其他应用程序在不被反复强制进入onStop() / onResume()当你的大象应用程序在安卓(Android)按摩浴缸里洗澡时,它们被粗鲁地从记忆中冲了出来。
据我所知,这种区别并没有被清楚地记录下来,但我已经在五种不同的Android设备上测试了这个假设(见下文),并且证实了这是一个正确的解释,这让我自己感到满意。
对于Android的股票版本,maxMemory()通常返回的兆字节数与getMemoryClass()(即约为后者价值的100万倍)。
这两种方法可能有分歧的唯一情况(我知道)是在运行Android版本的根设备上,比如CyanogenMod,它允许用户手动操作选择应该允许每个应用程序的堆大小有多大。例如,在CM中,此选项出现在“CyanogenMod设置”/“Performance”/“VM堆大小”下。
注意:请注意,手动设置此值可能会使您的系统陷入困境,特别是如果您选择一个比设备正常的值更小的值。
下面是我的测试结果,显示了maxMemory()和getMemoryClass()对于运行CyanogenMod的四个不同设备,对每个设备使用两个不同的堆值(手动设置):G1:最大记忆:25165824
getMemoryClass:16最大记忆:16777216
getMemoryClass:16将VM堆大小设置为16 MB:
将VM堆大小设置为24 MB:
Moto Droid:最大记忆:16777216
getMemoryClass:24最大记忆:25165824
getMemoryClass:24将VM堆大小设置为24 MB:
将VM堆大小设置为16 MB:
Nexus One:最大记忆:25165824
getMemoryClass:32最大记忆:33554432
getMemoryClass:32将VM堆大小设置为32 MB:
将VM堆大小设置为24 MB:
ViewSonic GTab:最大记忆:67108864
getMemoryClass:32最大记忆:33554432
getMemoryClass:32将VM堆大小设置为32:
将VM堆大小设置为64:
除此之外,我还在Novo7Paladin平板上测试了冰淇淋三明治。这本质上是ICS的一个普通版本,只不过我已经通过一个简单的过程来扎根平板电脑,这个过程并不取代整个操作系统,特别是没有提供一个允许手动调整堆大小的接口。
对于该设备,结果如下:11月7日最大记忆:62914560
getMemoryClass:60
另外(Kishore在下面的评论中):HTC One X最大记忆:67108864
getMemoryClass:64
(根据阿考皮的评论):三星Galaxy Core PlusmaxMemory:(未在注释中指定)
getMemoryClass:48
大型内存类:128
根据cmcromance的评论:GalaxyS3(果冻豆)大堆最大记忆:268435456
getMemoryClass:64
以及(根据腾讯的评论):LG Nexus 5(4.4.3)正常最大记忆:201326592
getMemoryClass:192
LG Nexus 5(4.4.3)大堆最大记忆:536870912
getMemoryClass:192
星系Nexus(4.3)正常最大记忆:100663296
getMemoryClass:96
GalaxyNexus(4.3)大堆最大记忆:268435456
getMemoryClass:96
GalaxyS4游戏商店版(4.4.2)正常最大记忆:201326592
getMemoryClass:192
GalaxyS4播放商店版(4.4.2)大堆最大记忆:536870912
getMemoryClass:192
其他装置华为Nexus 6P(6.0.1)正常最大记忆:201326592
getMemoryClass:192
我还没有使用特别的Android来测试这两种方法:largeHeap=“true”清单选项,从蜂巢开始就可以使用了,但是由于cmcromance和腾讯,我们确实有一些示例大堆值,正如上面所报告的。
我的期望(上面的大堆数似乎支持此选项),该选项将产生类似于通过根操作系统手动设置堆的效果-也就是说,它将提高maxMemory()离开时getMemoryClass()独自一人。还有另一种方法getLargeMemoryClass(),它使用LargeHeap设置指示应用程序允许多少内存。getLargeMemoryClass()的文档声明:“大多数应用程序不应该需要这样的内存量,而应该停留在getMemoryClass()限制中。”
如果我猜对了,那么使用该选项将与使用通过根操作系统提高堆的用户所提供的空间(即,如果您的应用程序使用附加内存,它可能不会很好地处理用户同时运行的任何其他应用程序)具有相同的好处(也会带来同样的危险)。
注意,内存类显然不需要是8MB的倍数。
从上面我们可以看到getMemoryClass()对于给定的设备/OS配置,结果是不变的,而当用户以不同的方式设置堆时,maxMemory()值就会发生变化。
我自己的实际经验是,在G1(它的内存类为16)上,如果我手动选择24 MB作为堆大小,即使允许我的内存使用量上升到20 MB(可能高达24 MB,尽管我还没有尝试),我也可以运行而不出错。但是其他类似的大型应用程序可能会因为我自己的应用程序的强大而从内存中消失。反过来说,我的如果其他高维护的应用程序被用户带到前台,应用程序可能会从内存中消失。
因此,您不能检查maxMemory()..而且,你应该试一试在getMemoryClass()..一种方法,如果其他所有的失败,可能是限制这类设备的功能,以节省内存的方式。
最后,如果您确实计划超过getMemoryClass(),我的建议是,在保存和恢复应用程序的状态方面努力工作很长时间,这样用户的体验实际上是不受干扰的,如果onStop() / onResume()循环发生。
在我的例子中,出于性能原因,我将我的应用程序限制在运行2.2和更高版本的设备上,这意味着几乎所有运行我的应用程序的设备都有一个内存类为24或更高的内存类。这样我就可以设计出可以占用多达20 MB的堆,并且非常有信心我的应用会和用户同时运行的其他应用程序保持良好的关系。
但是,总会有一些根深蒂固的用户将2.2或更高版本的Android加载到旧设备(例如G1)上。当您遇到这样的配置时,理想情况下,您应该减少内存使用,即使maxMemory()告诉你可以比16 MBgetMemoryClass()告诉你应瞄准目标。如果您不能可靠地确保您的应用程序能够在该预算范围内运行,那么至少要确保onStop() / onResume()天衣无缝。
getMemoryClass()正如上面的Diane Hackborne(Hackbod)所指出的,只能返回到API级别5(Android2.0),因此,正如她建议的那样,您可以假设任何运行操作系统早期版本的设备的物理硬件都是为了优化地支持占用堆空间不超过16 MB的应用程序而设计的。
相比之下,maxMemory(),根据文档,可以一直使用到API级别1。maxMemory(),在预2.0版本上,可能会返回一个16 MB的值,但是我做请注意,在我的(很久以后)的CyanogenMod版本中,用户可以选择一个低到12 MB的堆值,这可能会导致更低的堆限制,因此我建议您继续测试maxMemory()值,甚至对于2.0之前的操作系统版本也是如此。在设置此值甚至低于16 MB的情况下,您甚至可能不得不拒绝运行,如果您需要的是maxMemory()指示是允许的。