我有一个带有实例变量ImageView的A类。目前我使用setTag()从ImageView返回到A类的实例。这是否存在循环循环?我也听说过弱引用。获得ImageView的父类A的最佳方法是什么?
我的使用场景是我在屏幕上拖动ImageView,我需要访问A类以获取有关被拖动的ImageView的信息。
答案 0 :(得分:3)
我相信Dalvik VM在检测循环引用方面没有问题。
以下是对此进行讨论的问答:Circular References in Java
只有非常天真的实现才会出现循环问题 引用。
我会使用setTag来保存引用相关对象的引用。此外,在View上使用setTag / getTag是在Android上实现各种优化的标准和推荐方法,甚至可以在Android示例中找到。 一些参考文献:
http://www.vogella.de/articles/AndroidListView/article.html#ownadapter_viewHolder
如果Android的GC在检测此类依赖关系时遇到问题,Android将无法正常工作。 如果适合您的目的,请继续使用View.setTag。
答案 1 :(得分:1)
java中的循环引用不是GC的问题。由于称为“可达性”的概念,这不是问题。
您可以将对象引用视为有向图,其中节点是对象,边是对象引用。图中有一组称为“根节点”的节点 - 这些节点(大致)是vm中某些线程可直接访问的对象。任何函数中的局部变量都会调用堆栈,类中的静态字段等等。
执行垃圾收集时,VM从这些根节点开始,并将它们标记为“正在使用”。然后,对于从这些正在使用的节点中引出的每个边缘(即,对于从使用中对象引用的每个对象),它也标记为在使用中,依此类推,直到没有任何东西留给标记。然后,任何未标记为“正在使用”的对象,它知道它可以安全地进行垃圾收集。
现在,让我们假设您使用某种方法,并且您拥有以下代码:
a = new A();
a.b = b;
b = new B();
b.a = a
您现在在a和b之间有一个循环引用。这两个对象都是根集的一部分,因为它们是堆栈中方法调用中的局部变量。
然后,当您退出该方法时,a和b将不再是根集的一部分。只要你没有在其他地方引用它们,就没有别的东西可以引用a或b。
现在,您的对象引用图将包含一个包含a和b的图的一些断开连接的部分。他们俩仍然互相引用,但没有别的东西可以引用它们。由于它们无法从根集中访问,因此GC知道它们没有被使用并且可以垃圾收集它们 - 即使它们彼此有引用。
(请注意,这是一个有点简化的垃圾收集描述,但它仍然是一个有用/合理的心理模型,它是如何工作的)
所以简短的回答是 - “是的,你有一个循环引用。但这不是一个问题,因为一旦两个对象都不再可以转发,它们就会被收集”
答案 2 :(得分:0)
摆脱循环引用的最佳方法是将A中的实例变量设为最终变量:
private final ImageView myImageView;
这将强制您在A的构造函数中初始化变量。如果在新调用中明确地将引用传递给ImageView
,则将避免循环引用的可能性。
public A(ImageView iv, ...) {
this.myImageView = iv;
...
// associate this instance of A with ImageView?
this.imageView.setTag(this);
...
}