要撤消对模型的绑定(包括侦听器)时要考虑的要点:
-
无向绑定(
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!
嗯,这对于lambdas来说可能是显而易见的,但是对于方法引用也是如此,这真的很烦人:
// method references are not constant
Runnable runnable1 = this::anyMethod;
Runnable runnable2 = this::anyMethod;
assert runnable1 != runnable2; // they are NOT identical!
这意味着,如果希望能够注销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);
解决方案
您必须自己存储对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) { ... }
}