首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >绑定不在FXML控制器初始化()方法之外工作的对象

绑定不在FXML控制器初始化()方法之外工作的对象
EN

Stack Overflow用户
提问于 2019-04-27 09:28:29
回答 1查看 92关注 0票数 0

核心问题:如果绑定属性在声明绑定属性的initialize()方法之外更新,则不会触发Binding对象失效侦听器。

以在initialize() UI控制器类中声明的这个JavaFX方法为例:

代码语言:javascript
复制
@FXML
private void initialize() {
    final StringProperty stringProperty = textField.textProperty();
    stringProperty.addListener(
            (observable, oldValue, newValue) -> System.out.println("stringProperty value: " + newValue));
    Bindings.createStringBinding(() -> "PREFIX - " + stringProperty.getValue(), stringProperty).addListener(
            (observable, oldValue, newValue) -> System.out.println("StringBinding value: " + newValue));

    // Editing stringProperty value inside initialize() method
    stringProperty.setValue("u");
    stringProperty.setValue("ua");
    stringProperty.setValue("ua");
    stringProperty.setValue("uaa");
}

正如您在这里看到的,我声明了一个依赖于一个名为StringBinding的TextField的text属性的ChangeListener,以及一个当它变得无效时请求计算StringBindingChangeListener

如果在初始化方法中编辑stringProperty值,则会触发stringPropertyStringBinding更改侦听器,而如果从UI编辑stringProperty值,则只触发stringBinding更改侦听器。

有人能解释一下为什么会发生这种事吗?

EN

Stack Overflow用户

回答已采纳

发布于 2019-04-27 19:17:09

由于不存在对由StringBinding创建的Bindings.createStringBinding的强引用,因此最终将被垃圾收集。一旦发生这种情况,您添加的侦听器将与其一起被垃圾收集。

我不认为这是因为Binding对象通过InvalidationListener监听它们的依赖项(Observable对象),而Obsevable.addListener(InvalidationListener)文档指出,“可观察到的存储对侦听器的强烈引用,这将防止侦听器被垃圾收集,并可能导致内存泄漏。”

这是正确的,但是看看XXXBinding类使用的侦听器实现:

代码语言:javascript
复制
/*
 * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.javafx.binding;

import java.lang.ref.WeakReference;

import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.WeakListener;
import javafx.beans.binding.Binding;

public class BindingHelperObserver implements InvalidationListener, WeakListener {

    private final WeakReference<Binding<?>> ref;

    public BindingHelperObserver(Binding<?> binding) {
        if (binding == null) {
            throw new NullPointerException("Binding has to be specified.");
        }
        ref = new WeakReference<Binding<?>>(binding);
    }

    @Override
    public void invalidated(Observable observable) {
        final Binding<?> binding = ref.get();
        if (binding == null) {
            observable.removeListener(this);
        } else {
            binding.invalidate();
        }
    }

    @Override
    public boolean wasGarbageCollected() {
        return ref.get() == null;
    }
}

如您所见,添加到依赖项(即Observables)的侦听器实例是一个WeakListener,并且只维护对Binding的弱引用。这允许垃圾收集Binding,即使它没有被正确地处理。这样做是为了帮助防止内存泄漏,如果Binding已经超出了范围,但是Observable没有。

换句话说,Observable维护对InvalidationListener的强引用,而InvalidationListener维护对Binding的弱引用。

这类行为记录在“远程”位置,包括Property#bind(ObservableValue)

为此Property创建单向绑定。 请注意,JavaFX具有通过弱侦听器实现的所有绑定调用。这意味着绑定属性可以被垃圾收集并停止更新。

Binding#dispose()

Binding发出信号,表示它将不再被使用,任何引用都可以删除。此方法的调用通常导致绑定停止,通过注销侦听器来观察其依赖关系。实现是可选的。 我们实现中的所有绑定都使用WeakInvalidationListener实例,这意味着通常不需要处理绑定。但是,如果计划在不支持WeakReferences的环境中使用应用程序,则必须释放未使用的Binding,以避免内存泄漏。

注意:实现似乎没有使用WeakInvalidationListener__,但是效果是相同的。

票数 0
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55879079

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档