JavaFX:绑定和弱监听器

3

来自JavaFX bind()方法 Javadoc

请注意,JavaFX通过弱引用监听器实现所有的绑定调用。这意味着绑定属性可以被垃圾回收并停止更新。

现在考虑我有两个属性,ObjectProperty<Foo> shortLived 存在于 ShortLivedObject,以及 ObjectProperty<Foo> longLived 存在于 LongLivedObject

我将它们绑定如下:

longLivedObject.longLivedProperty().bind(shortLivedObject.shortLivedProperty());

由于绑定使用了弱监听器,所以如果shortLivedObject被垃圾回收,shortLived属性也将被垃圾回收。那么,这是否意味着longLived属性仍然处于绑定状态,但永远不会更新?这是否使得longLived属性处于绑定状态(使进一步的绑定不可能),但又无任何作用?

我认为JavaDoc所说的是longLivedProperty的监听器,它被用于监听shortLivedObject的变化,可能会因为采用WeakReference 被垃圾回收。 除非你持有对longLivedProperty的强引用,这将防止其监听器被垃圾回收。 因此,JavaDoc并没有说shortLivedProperty将被垃圾回收。那么,你为什么期望shortLivedProperty被垃圾回收呢? - shaka-b
1个回答

1
所以,这是否意味着longLived属性仍然绑定,但它将永远不会被更新?
假设shortLivedProperty已经被垃圾回收,那么shortLivedProperty将不再被使无效。因此,longLived的监听器将永远不会被调用和更新。
这是否留下了longLived属性处于绑定状态(使进一步绑定变得不可能),但什么也没有做?
您应该始终能够将属性绑定到新的observable上,而不管绑定状态如何,因为旧的observable属性将被删除/解除绑定:
public void bind(final ObservableValue<? extends T> newObservable) {
    if (newObservable == null) {
        throw new NullPointerException("Cannot bind to null");
    }

    if (!newObservable.equals(this.observable)) {
        unbind();
        observable = newObservable;
        if (listener == null) {
            listener = new Listener(this);
        }
        observable.addListener(listener);
        markInvalid();
    }
}

在查找源代码时,我发现了一些有趣的东西。如果this.observable是当前属性监听更改的另一个属性,那么当前属性不就持有另一个属性的强引用吗?因此,他们将监听器设置为弱引用,但保留了另一个属性的引用... - Jai
这就是为什么我问你“为什么你期望shortLivedProperty被垃圾回收”?据我所知,这不应该发生,因为根据你的描述,shortLivedProperty至少从longLivedProperty强可达。 - shaka-b
好的,Javadoc上说:这意味着绑定属性可以被垃圾回收。但是在看了源代码之后,这个说法被证明是彻头彻尾的谎言。 - Jai
1
bound property 指的是 longLivedProperty,因为 longLivedPropertyshortLivedProperty 绑定。实际上,如果 longLivedProperty 可以被弱引用,那么它可能会被垃圾回收。也就是说,如果您没有对 longLivedProperty 有一个强引用,它可能会被回收。 - shaka-b

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