SoftReference太早收集垃圾

我正在为我的Android应用程序实现缓存机制。

我使用SoftReference ,就像我发现的许多例子一样。 问题是,当我在ListView向上或向下滚动时, 大部分图像已被清除。 我可以在LogCat中看到每次应用程序加载新图像时我的应用程序都是垃圾收集的。 这意味着ListView中的大多数不可见图像都消失了。

因此,每次我回滚到较早的位置(之前我真的下载过图像)我必须再次下载图像 – 它们不会被 缓存

我也研究过这个话题。 根据Mark Murphy在本文中的说法, SoftReference似乎存在(或者是?)错误。 其他一些结果表明相同(或相同的结果); SoftReference太早被清除了。

有没有可行的解决方案?

SoftReference是可怜的勒芒。 JVM可以将这些引用保持更长时间,但不必。 只要没有硬引用,JVM就可以垃圾收集软引用的Object。 您遇到的JVM的行为是正确的,因为JVM不必更长时间地保持这样的对象。 当然,大多数JVM都试图在某种程度上保持软参考对象的存活。

因此,SoftReferences是一种危险的缓存。 如果您确实想要确保缓存行为,则需要一个真正的缓存。 像LRU缓存一样 。 特别是如果你的缓存是性能关键的,你应该使用适当的缓存。

来自Android培训网站:

http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html

过去, 流行的内存缓存实现是SoftReference或WeakReference位图缓存,但不建议这样做。 从Android 2.3(API级别9)开始,垃圾收集器更积极地收集软/弱引用,这使得它们相当无效 。 此外,在Android 3.0(API Level 11)之前,位图的后备数据存储在本机内存中,而该内存未以可预测的方式发布,可能导致应用程序短暂超出其内存限制并崩溃。

链接中的更多信息。

我们应该使用LruCache 。

将每个映像缓存在持久存储上而不是仅存储在内存中。

Gamlor的答案在你的情况下是正确的。 但是,有关其他信息,请参阅GC常见问题解答 ,问题32。

Java HotSpot Server VM使用最大可能的堆大小(由-Xmx选项设置)来计算剩余的可用空间。

Java HotSpot Client VM使用当前堆大小来计算可用空间。

这意味着服务器VM的总体趋势是增加堆而不是刷新软引用,因此-Xmx对软引用何时进行垃圾回收具有显着影响。