我只对天气属性有变化感兴趣,但不是新值.
是否有利于注册InvalidationListener而不是ChangeListener?
我假设,对属性的更改首先使属性失效并通知所有失效侦听器.只有在注册了更改侦听器或者有人请求此属性时,才会"验证"/重新计算该属性,并使用新值更新所有更改侦听器.
由于我对实际值不感兴趣,因此我认为仅监听失效事件(属性已更改但未重新计算,某种中间状态)是一种性能优势.
Ort*_*ier 10
你需要实现一个ChangeListener.A InvalidationListener仅在值变为无效时执行.查看文档.
来自ObservableValue的java文档:
ObservableValue生成两种类型的事件:更改事件和失效事件.更改事件表示值已更改.如果当前值不再有效,则生成失效事件.如果ObservableValue支持延迟评估,则这种区别变得很重要,因为对于延迟评估的值,在重新计算之前,无法确定无效值是否确实已更改.出于这个原因,生成更改事件需要急切评估,同时可以为急切和懒惰的实现生成无效事件.
我添加了一个简单的例子
public static void main(String[] args) {
SimpleIntegerProperty one = new SimpleIntegerProperty(1);
SimpleIntegerProperty two = new SimpleIntegerProperty(0);
// the binding we are interested in
NumberBinding sum = one.add(two);
sum.addListener(observable -> System.out.println("invalidated"));
// if you add a value change listener, the value will NOT be evaluated lazy anymore
//sum.addListener((observable, oldValue, newValue) -> System.out.println("value changed from " + oldValue + " to " + newValue));
// is valid, since nothing changed so far
System.out.println("sum valid: " + sum.isValid());
// will invalidate the sum binding
two.set(1);
one.set(2); // invalidation event NOT fired here!
System.out.println("sum valid: " + sum.isValid());
// will validate the sum binding, since it is calculated lazy when getting the value
System.out.println("sum: " + sum.getValue());
System.out.println("sum valid: " + sum.isValid());
}
Run Code Online (Sandbox Code Playgroud)
使用它的问题InvalidationListener是,如果值再次变为无效,则不会通知您更改,因为它已经无效.您必须为此使用更改侦听器.
在属性上注册更改侦听器将禁用延迟评估,因此每次更改侦听器被触发时都会触发invalidation事件.
在我添加的样本中尝试一下.
从书中:
仅当其内容的状态从有效变为无效时,可观察对象才应生成失效事件。也就是说,连续多次失效应该只产生一个失效事件。
一个小例子来说明
public class stackOverflowListenerQuestion extends Application {
public static void main( String[] args ) {
launch();
}
@Override
public void start( Stage primaryStage ) throws Exception {
IntegerProperty money = new SimpleIntegerProperty(1);
money.addListener(observable -> System.out.println("we should notify the listener"));
money.set(10);
money.set(20);
money.set(30);
System.out.println(money.getValue());
IntegerProperty moreMoney = new SimpleIntegerProperty(1);
moreMoney.addListener(( observable, oldValue, newValue ) -> System.out.println("we should notify the listener very quickly"));
moreMoney.set(100);
moreMoney.set(200);
moreMoney.set(300);
System.out.println(moreMoney.getValue());
Platform.exit();
}
}
Run Code Online (Sandbox Code Playgroud)
输出
we should notify the listener
30
we should notify the listener very quickly
we should notify the listener very quickly
we should notify the listener very quickly
300
Run Code Online (Sandbox Code Playgroud)
与money属性关联的侦听器类型为Invalidationlistener,从输出中我们可以看到InvalidationListener和之间在事件方面的差异ChangeListener。
一个更详细的例子:
public class InvalidationListener extends Application {
public static void main( String[] args ) {
launch();
}
@Override
public void start( Stage primaryStage ) throws Exception {
Person p1 = new Person();
Person p2 = new Person();
Person p3 = new Person();
NumberBinding total = Bindings.add(p1.moneyProperty().add(p2.moneyProperty()), p3.moneyProperty());
//to see the differences between InvalidationListener and ChangeListener, yous should test them separately and watch the printed result to understand.
// total.addListener(( observable, oldValue, newValue ) -> System.out.println("change event occurred, we should notify the listeners"));
total.addListener(observable -> System.out.println("Invalidation occurred, we should notify the listeners but lazily"));
p1.setMoney(100);
System.out.println("total.isValid() = " + total.isValid());
p2.setMoney(200);
System.out.println("total.isValid() = " + total.isValid());
p3.setMoney(200);
System.out.println("total.isValid() = " + total.isValid());
System.out.println("total = " + total.getValue());
System.out.println("total.isValid() = " + total.isValid());
p3.setMoney(150);
System.out.println("total.isValid() = " + total.isValid());
System.out.println("total = " + total.getValue());
System.out.println("total.isValid() = " + total.isValid());
Platform.exit();//shutdown the JavaFx Application Thread
}
static class Person{
private IntegerProperty money = new SimpleIntegerProperty();
public final int getMoney() {
return money.get();
}
public final void setMoney( int money ) {
this.money.set(money);
}
public IntegerProperty moneyProperty() {
return money;
}
}
}
Run Code Online (Sandbox Code Playgroud)
当您使用 时ChangeListener,只要发生更改就会触发一个事件。当您使用InvalidationListener它时,情况并非如此。
来自同一本书
当属性值的状态第一次从有效变为无效时,属性会生成失效事件。JavaFx 中的属性使用惰性求值。当无效属性再次变为无效时,不会生成失效事件。无效属性在重新计算时变为有效,例如,通过调用其 get() 或 getValue() 方法。