Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
248 views
in Technique[技术] by (71.8m points)

java - JavaFX InvalidationListener or ChangeListener

I am only interested whether a property has changed or not, but not in the new value.

Is it advantageous to register an InvalidationListener instead of a ChangeListener?

I was assuming that a change to a property does first invalidate the property and notifies all invalidation listeners. Only if there are change listeners registered, or somebody requests this property, the property is 'validated'/ re-computed and all change listeners are updated with the new value.

Since I am not interested in the actual value, I assume it is a performance advantage to listen only for invalidation events (property has changed but was not re-calculated, some kind of intermediate state).

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You need to implement a ChangeListener for that. A InvalidationListener is only executed once the value becomes invalid. See the docs.

From the java docs of ObservableValue:

An ObservableValue generates two types of events: change events and invalidation events. A change event indicates that the value has changed. An invalidation event is generated, if the current value is not valid anymore. This distinction becomes important, if the ObservableValue supports lazy evaluation, because for a lazily evaluated value one does not know if an invalid value really has changed until it is recomputed. For this reason, generating change events requires eager evaluation while invalidation events can be generated for eager and lazy implementations.

I have added a simple example

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

The problem in using the InvalidationListeneris that you will not be notified for changes if the value becomes invalid again, since it is already invalid. You have to use a change listener for that.

Registering a change listener on the property will disable lazy evaluation, so the invalidation event gets fired every time the change listener gets fired.

Try it out in the sample i added.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...