弱引用相关问题

3

我在我的程序中有一两个弱引用

举个例子:

ClassX myClassX= new ClassX(); //Line 1
WeakReference<ClassX> myWeakClassX = new WeakReference<ClassX>(myClassX); //Line 2
if(myWeakClassX.get() != null) // Line 3
{
    //do something with reference //Line 4
}

我的问题:

如何确保当在第3行myWeakClassX.get()拥有一个指向Object的有效引用时,它在第4行也是有效的?我可以想象,如果你运气不好,在第3行和第4行之间垃圾回收器会做他的工作。请容忍我,因为我相对于Android/Java是比较新的。

感谢任何解释。

2个回答

2
您说的对,在第3行和第4行,get() 操作可能会返回 null ,这是它应该做的。您可以将从 get() 操作获得的引用复制到一个变量中(从而使其再次强引用),并在 if 块内安全使用它。因为您仍然拥有一个强引用,所以对象不会被垃圾回收。
检查是否为 null 的一个简单方法是:
if(myWeakClassX.get() != null)
{
  ClassX myref = myWeakClassX.get();
  if(myref != null) {
      //use it
  }
}

然而,在活动方面,强引用并不能保证该活动不会被销毁。即使您拥有一个有效的强引用,当您尝试使用已经被销毁的活动时,该活动可能会抛出异常。 例如:如果您在某个AsyncTask中保留了一个活动的引用,那么在AsyncTask运行之前,该活动可能会被销毁(如屏幕旋转)。虽然您仍然拥有对该活动的引用,但是当您尝试更新UI时,会出现异常。 这就是为什么您可以在AsyncTask中创建一个对活动的弱引用。如果get()操作开始返回null,则表示该活动由于某种原因已被销毁,并且不再尝试使用它。

如果我将从get()方法获取的引用放入if-scope中并转换为strong-reference,那么没有人能确保在那一点上它不是null。对我来说,这只是将问题移动到“另一个地方”。也许在这种情况下使用Softreference更好?实际上,只有使用strongreference才能确保您拥有有效的引用。那么,如果它们可能导致NPE,为什么要使用weak-or softreferences呢? - MMike
我已经给出了一个关于Activities的WeakReference示例。如果你在某个AsyncTask中保留了对Activity的引用,那么在AsyncTask运行之前,Activity可能会被销毁(例如方向更改)。尽管你仍然有对它的引用,但当你尝试更新UI时,你将会收到异常。在弱引用的情况下,你总是可以检查是否为null - 请查看更新的答案。 - ata
现在我明白了。你是对的。并且在 if-语句 结束后,强引用就可以被垃圾回收器回收,对吗? - MMike
是的,引用将会超出范围。垃圾回收器可以在任何时候进行回收。 - ata
谢谢,只能接受一个答案,所以你得到了我的赞。 - MMike

2
在Java中,首先要理解的是垃圾收集器从符合垃圾回收条件的对象中回收内存。
问题是如何定义符合条件?
符合条件取决于指向该对象的引用类型。
为什么需要弱引用?
如果您创建一个强引用到一个对象,那么该对象将无法被垃圾回收。而弱引用简单地说就是一种不足以强制对象保留在内存中的引用。弱引用允许您利用垃圾收集器的可达性判断能力,因此您不必自己进行操作。
问题在于,弱引用不足以防止垃圾回收,因此如果没有对该类的强引用,您可能会发现myWeakClassX.get()突然返回null。
另一个选择是什么?
软引用
当您希望所引用的对象在主机进程的内存不足时仍然保持活动状态时,可以使用SoftReference。直到收集器需要释放内存为止,该对象将不符合垃圾回收条件。粗略地说,绑定SoftReference意味着“将对象固定在内存中,直到无法再这样做为止”。
这样,myWeakClassX.get() 就不会是 null。
可以使用 ? 的示例:
1. 在任何创建对 activity 引用的次要线程中。 WeakReference weakActivity; //在 AsyncTask onPostExecute 方法中 Activity activity = weakActivity.get(); if (activity != null) { //在这里处理 activity }
2. 如果您在其他地方引用 Activity 上下文,则可以使用弱引用。
3. 在另一个线程中处理 ImageView 中的位图资源时 http://developer.android.com/training/displaying-bitmaps/process-bitmap.html 4. 如果您正在创建任何 HashMap 或任何小部件来保存任何数据,则可以使用弱引用。http://developer.android.com/reference/java/util/WeakHashMap.html 5. 使用是无限的。开发人员可以在正确的地方使用它。

听起来不错,但是在第3行和第4行之间如果内存不足,即使使用softreference也会返回null。那么为什么要使用weak-or-softreferences呢?如果您无法确保它们返回null,那么您的程序可能会因为NPE而崩溃。 - MMike
@MMike,如果你的Android操作系统出现低内存警告,所有低优先级的活动即使对象保持强引用也将被垃圾回收。但我们需要不同的引用来管理GC的资格行为。因此,在正确的位置使用弱/软引用是很好的选择。 - Prem
听起来很有道理。你能告诉我一些正确使用它们的例子吗?感激不尽。 - MMike

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接