我有一个带有SimpleXXXXProperty属性的模型类。Javafx GUI元素使用绑定或更改侦听器进行更新,例如
textField.textProperty().bind(myModel.myModelStatus());
Run Code Online (Sandbox Code Playgroud)
要么
myModel.myModelStatus().addListener((obj,oldv.newv) -> { update here });
Run Code Online (Sandbox Code Playgroud)
当模型类的实例更改时,我将重新绑定控件并再次添加侦听器。但是,通过内存使用,我可以看到旧模型仍保留在内存中。
我该怎么做才能删除对模型的所有引用,以便可以对其进行清理?
当父属性更改时,是否有更自动的方法来更新嵌套属性上的绑定和侦听器?
想要撤消对模型的绑定(包括侦听器)时要考虑的要点:
p1.bind(p2)相同属性(例如p1.bind(p3))时,无方向绑定()会自动解除绑定,但是明确地进行绑定()也不会受到损害p1.unbind()。p1.bindBidirectional(p2)或Bindings.bindBidirectional(p1, p2))必须明确地解除绑定(p1.unbindBidirectional(p2)或Bindings.unbindBidirectional(p1, p2))。prop.removeListener(l))。第三是棘手的部分,因为侦听器通常实现为lambda表达式或方法引用。(!)不幸的是,lambda表达式以及方法的引用是不是常数:
// lambdas are not constant
InvalidationListener l1 = obs -> {};
InvalidationListener l2 = obs -> {};
assert l1 != l2; // they are NOT identical!
Run Code Online (Sandbox Code Playgroud)
嗯,这对于lambda来说可能是显而易见的,但对于方法引用也是如此,这确实很烦人:
// method references are not constant
Runnable runnable1 = this::anyMethod;
Runnable runnable2 = this::anyMethod;
assert runnable1 != runnable2; // they are NOT identical!
Run Code Online (Sandbox Code Playgroud)
这意味着,如果您想取消注册lambda表达式或简单的方法引用,则不能将其注册为侦听器:
// if you register listeners on a property like that...
label.textProperty().addListener(obs -> System.out.println(obs));
label.textProperty().addListener(this::handleLabelInvalid);
// ...these calls WON'T remove them due to the inequality shown above!
label.textProperty().removeListener(obs -> System.out.println(obs));
label.textProperty().removeListener(this::handleLabelInvalid);
Run Code Online (Sandbox Code Playgroud)
解
您必须自己存储对lambda表达式或方法引用的引用。我通常使用final字段:
public class MyClass {
// store references for adding/removal
private final InvalidationListener l1 = this::handleLabelInvalid;
private final InvalidationListener l2 = obs -> System.out.println(obs);
...
public void bind() {
label.textProperty().addListener(l1);
label.textProperty().addListener(l2);
}
public void unbind() {
label.textProperty().removeListener(l1);
label.textProperty().removeListener(l2);
}
private void handleLabelInvalid(Observable observable) { ... }
}
Run Code Online (Sandbox Code Playgroud)