我的应用程序中有一个使用SoftReferences实现的图像缓存。 Dalvik以相对较小的堆启动应用程序,然后在需求的情况下增加它。但我想从一开始就让我的堆大小更大。这是因为当我已经在缓存中有一些图像,并且活动开始(例如)或其他峰值内存需求发生时,我的缓存被清除,以便为该峰值需求提供内存。结果,在峰值消失后,我仍然有2-3 MB的可用空间,但我的缓存是空的!
我看到的解决这个问题的解决方案是预先分配一个更大的正式堆,因此即使峰值消耗为2-3 MB,它仍然有一些空间,因此我的SoftReferences不会被清除。
我发现VMRuntime.getRuntime().setMinimumHeapSize(BIGGER_SIZE)
会有所帮助。特别是,谷歌在他们的应用程序中使用它,如上所述here。但是,VMRuntime类被标记为已弃用,并且在将来的版本中表示将从公共API中删除。所以setMinimumHeapSize
不是永久的解决方案。
然后我如何让Dalvik在启动时增加我的堆?
目前,我只需分配一个大型数组并释放它,就可以使用一种非常简单和俗气的技术。这使得Dalvik成长为我想要的堆。但是,我确信必须有更优雅的方式。你能告诉我吗?
答案 0 :(得分:6)
您可以更好地做一些事情,而不是增加堆大小。正如您所说,您在使用SoftReferences实现的应用程序中维护缓存。最好的事情是使用LruCache你可以做这样的事情:
private LruCache<String, Bitmap> bitmapCache;
final int memClass;
int cacheSize;
memClass = ((ActivityManager) context.getSystemService(
Context.ACTIVITY_SERVICE)).getMemoryClass();
返回当前设备的近似每应用程序内存类。这可以让您了解应该对应用程序施加的内存限制有多难,以使整个系统最佳运行。返回值以兆字节为单位;基线Android内存类是16(恰好是这些设备的Java堆限制);一些具有更多内存的设备可能会返回24或更高的数字。
cacheSize = 1024 * 1024 * memClass / 10;
bitmapCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getHeight() * value.getRowBytes();
}
};
如果内存超出LruCache的内存并加载新图像,它将从LruCache中删除位图图像。
答案 1 :(得分:4)
如果您说的缓存通常很小,您可以自己决定应用程序的有效占用空间,并在没有SoftReferences的情况下维护自己的缓存。
例如,通过简单的总字节计数器:只需添加或移动用于列表顶部的任何元素,如果它是新的,则将其大小添加到计数器。如果总字节数超过了经验法则限制,则从底部删除,从而减少计数器。也许LinkedHashMap
类对此有用:它可以像HashMap
一样用作缓存,但它的顺序也像列表一样。
答案 2 :(得分:2)
问题是SoftReferences对于在Java堆空间中完成的分配很有用,但是图像是本机分配的,因此这种缓存类型在Android上不会真正起作用。
答案 3 :(得分:1)
您无法动态增加堆大小。
你可以在清单中使用android:largeHeap =“true”请求使用更多,但你可能不会获得比正常更多的堆大小,因为它只是一个请求。
另外,您可以使用本机内存,因此实际上绕过了堆大小限制。
这里有一些关于它的帖子:
这是我为它制作的图书馆:
答案 4 :(得分:0)
我认为你不能或不应该在这个级别影响设备的内存。让系统做它的事情,不要反对它。即使活动开始,您是否需要使用SoftReferences来保存这么大的图像缓存?
您想要检查货架上的工作方式:请参阅http://code.google.com/p/shelves/source/browse/trunk/Shelves/src/org/curiouscreature/android/shelves/util/ImageUtilities.java?r=26
中的第82行