2017-07-15 80 views
1

我只是感兴趣的天气财产已经改变或没有改变,但没有在新的价值。JavaFX InvalidationListener或ChangeListener

是否有利于注册InvalidationListener而不是ChangeListener

我假设,对属性的更改首先使该属性无效并通知所有无效侦听器。只有注册了更改监听器,或者有人请求此属性时,该属性才会被“验证”/重新计算,并且所有更改监听器都将更新为新值。

由于我对实际价值不感兴趣,我认为只侦听失效事件(属性已更改但未重新计算,某种中间状态)是性能优势。

+0

此[说明](https://stackoverflow.com/a/33834626/230513)可能会有所帮助。 – trashgod

+0

谢谢,我已经更新了这个问题。 – kerner1000

回答

1

您需要为此执行ChangeListener。一旦该值变为无效,则仅执行InvalidationListener。请参阅docs

ObervableValue的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()); 
} 

在使用InvalidationListener的问题是,你不会更改通知如果值再次变得无效,因为它已经是无效的。您必须为此使用更改侦听器。

在属性上注册更改侦听器将禁用惰性评估,因此每次更改侦听器被触发时都会触发invalidation事件。

尝试一下我添加的示例。

+0

但是,当它改变时,值并不总是首先变为无效的? – kerner1000

+0

是的,但只有一次,直到再次验证(通过调用属性的获取者)。因此,如果您多次设置该值,则只会注意到该值的第一次更改,其他更改不会触发该事件。 –

+1

非常感谢,很好的答案,现在它非常清晰。 – kerner1000