11

我想将WeakReferences 用作(android)位图缓存的一部分,以便能够检查何时不再使用位图。

我的缓存的最大大小小于 Java 堆空间。当一个新的位图溢出缓存时,它应该放弃不再需要的位图。

WeakReference我的问题:什么时候返回 null的 get() 方法?

  1. 一旦不再有对该对象的强引用?(并且 GC 还没有发生)
  2. 或者当 GC 运行并确定它们不再是对该对象的强引用时?

如果 2. 是真的,那么我可能会遇到我的缓存可能会填满并且 GC 最近由于某种原因没有运行的情况。

然后,即使我在最后一次 GC 运行后已经放弃了引用,WeakReference#get()仍然会返回该对象,并且我的缓存不会将其清除。

4

4 回答 4

13

答案是这取决于您使用的 Android 版本。在 2.3 时间框架的某个地方,Android 改变了它的处理或弱引用。以前,它会在 GC 运行时删除它们。从 2.3 的某些版本(2.3.3?)开始,它会在最后一个强引用消失后立即删除它们。所以在现代版本的 Android 中,弱引用是没有用的。

在此更改之前,弱引用用于缓存。他们不再工作。现在正确的方法是使用 LRUCache。如果您需要支持旧版本,请使用支持库向后移植 LRU 缓存。

经过一番搜索,我认为更改是在 3.0 中进行的,而不是 2.3。不过,解决方案是相同的。

于 2013-05-23T19:08:27.367 回答
5

一旦 GC 确定对象是弱可达的,WeakReference 就会被清除。

这接近你的第二种情况。然而,弱可达性不仅需要没有强引用,还需要没有软引用。

来自java.lang.ref的 Java 包文档:

软引用和弱引用在添加到它们注册的队列(如果有)之前由收集器自动清除。

...

一个对象是弱可达的,如果它既不是强可达也不是软可达,但可以通过遍历弱引用来达到。当对弱可达对象的弱引用被清除时,该对象就有资格进行终结。

于 2013-05-23T18:43:31.910 回答
5

要缓存位图,请使用 SoftReference 而不是 Weak。GC 会在失去所有可能破坏缓存目的的强引用和软引用后立即清除 WeakReference。SoftReference 只有在内存不足的情况下才会被清除。并且保证 GC 会在抛出 OOME 之前运行。

于 2013-05-23T19:09:59.713 回答
-3

如其他答案所述,一旦指向的对象没有更多的强/软引用并且GC 已回收内存,WeakReference 将返回 null。

根据更一般的规则,我认为 Weak/SoftReferences 在应用程序中并不是一件好事。它使您的混合担忧:

  • 您的应用程序是关于业务逻辑的
  • JVM 和 Dalvik 是关于内存管理和代码优化的。

当您开始使用弱/软引用时,您会在应用程序中引入内存管理的问题,这使得开发/调试/理解变得更加困难。

您可能希望使用固定大小(元素数量或位图大小)的 LRU 缓存。

希望有帮助!

于 2013-05-26T09:04:34.283 回答