2017-07-15 2 views
1

Ich bin nur daran interessiert, dass sich eine Eigenschaft geändert hat oder nicht, aber nicht im neuen Wert.JavaFX InvalidationListener oder ChangeListener

Ist es vorteilhaft, eine InvalidationListener anstelle einer ChangeListener zu registrieren?

Ich ging davon aus, dass eine Änderung an einer Eigenschaft zuerst die Eigenschaft ungültig macht und alle Ungültigkeitslistener benachrichtigt. Nur wenn Änderungslistener registriert sind oder jemand diese Eigenschaft anfordert, wird die Eigenschaft "validiert"/neu berechnet und alle Listener werden mit dem neuen Wert aktualisiert.

Da ich mich nicht für den tatsächlichen Wert interessiere, nehme ich an, dass es ein Leistungsvorteil ist, nur auf Ungültigkeitsereignisse zu warten (Eigenschaft hat sich geändert, wurde aber nicht neu berechnet, irgendeine Art Zwischenzustand).

+0

Diese [Erklärung] (https://stackoverflow.com/a/33834626/230513) kann hilfreich sein. – trashgod

+0

Danke, ich habe die Frage aktualisiert. – kerner1000

Antwort

1

Sie müssen eine ChangeListener dafür implementieren. A InvalidationListener wird nur ausgeführt, wenn der Wert ungültig wird. Siehe die docs.

aus der Java-Dokumentation von ObervableValue:

Ein ObservableValue erzeugt zwei Arten von Ereignissen: Änderungsereignisse und Ungültigkeits Veranstaltungen. Ein Änderungsereignis zeigt an, dass der Wert geändert wurde. Ein Ungültigkeitsereignis wird generiert, wenn der aktuelle Wert nicht mehr gültig ist. Diese Unterscheidung wird wichtig, wenn der ObservableValue Lazy Evaluation unterstützt, denn für einen träge ausgewerteten Wert weiß man nicht, ob ein ungültiger Wert wirklich geändert hat, bis er neu berechnet wird. Aus diesem Grund erfordert das Generieren der Änderung Ereignisse eifrige Evaluierung, während die Ereignisse für eifrige und faule Implementierungen generiert werden können.

Ich habe ein einfaches Beispiel

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

Das Problem hinzugefügt, um die InvalidationListener in Verwendung ist, dass Sie werden nicht für Änderungen benachrichtigt werden, wenn der Wert ungültig wird wieder, da es bereits ungültig ist. Sie müssen dafür einen Change Listener verwenden.

Durch die Registrierung eines Änderungs-Listeners für die Eigenschaft wird die Lazy-Evaluierung deaktiviert, sodass das Invalidierungsereignis jedes Mal ausgelöst wird, wenn der Change-Listener ausgelöst wird.

Probieren Sie es in der Probe, die ich hinzugefügt habe.

+0

Wird ein Wert nicht immer zuerst ungültig, wenn er sich ändert? – kerner1000

+0

Ja ist es, aber nur einmal, bis es erneut validiert wird (durch Aufruf des Getters der Eigenschaft). Wenn Sie also den Wert mehrmals setzen, werden Sie nur auf die erste Änderung des Wertes aufmerksam, weitere Änderungen werden das Ereignis nicht auslösen. –

+1

Vielen Dank, nette Antwort, es ist jetzt völlig klar. – kerner1000

Verwandte Themen