This discussion is archived
0 Replies Latest reply: Jan 5, 2013 2:24 AM by editOr RSS

Difference between InvalidationListener and ListChangeListener

editOr Newbie
Currently Being Moderated
Hi

Even though it's more of a "philosophical" question maybe you can help me out... :-D

Obviously ChangeListeners and InvalidationListeners are not always executed at the same time when used on a Property.

However, this seems not to be the case for ListChangeListener and InvalidationListeners used on ObservableLists. According to an example in the book "Pro JavaFx 2" it seems as if in this case both listeners are always executed at the same time. The book even states: "Although it is not specified in the Javadocs, for observable lists obtained by calling FXCollections.observableArrayList() a invalidation event is fired exactly when a list change event is fired. Any invalidation listener you add is wrapped and added as a list change listener. You can verify this by stepping
through the code in a debugger."
package crp;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
public class ObservableListExample {
     public static void main(String[] args) {
          ObservableList<String> strings = FXCollections.observableArrayList();
          strings.addListener(new InvalidationListener() {
               @Override
               public void invalidated(Observable observable) {
                    System.out.println("\tlist invalidated");
               }
          });
          strings.addListener(new ListChangeListener<String>() {
               @Override
               public void onChanged(Change<? extends String> change) {
                    System.out.println("\tstrings = " + change.getList());
               }
          });
          System.out.println("Calling add(\"First\"): ");
          strings.add("First");
          System.out.println("Calling add(0, \"Zeroth\"): ");
          strings.add(0, "Zeroth");
          System.out.println("Calling addAll(\"Second\", \"Third\"): ");
          strings.addAll("Second", "Third");
          System.out.println("Calling set(1, \"New First\"): ");
          strings.set(1, "New First");
          final List<String> list = Arrays.asList("Second_1", "Second_2");
          System.out.println("Calling addAll(3, list): ");
          strings.addAll(3, list);
          System.out.println("Calling remove(2, 4): ");
          strings.remove(2, 4);
          final Iterator<String> iterator = strings.iterator();
          while (iterator.hasNext()) {
               final String next = iterator.next();
               if (next.contains("t")) {
                    System.out.println("Calling remove() on iterator: ");
                    iterator.remove();
               }
          }
          System.out.println("Calling removeAll(\"Third\", \"Fourth\"): ");
          strings.removeAll("Third", "Fourth");
     }
}
This is useful to know and wasy to accept (if known), but nevertheless for a better understanding i'd like to know the reason for this behaviour. Without knowing the example above I would have thought that a InvalidationListener is executed if anything "changes" and is not already invalid (similar to the case of a property), that the changeListener is only executed when the changes are "asked for". For example when printing out. For a simple "add" (without using the newly added value) I therefore expected the invalidationListener to be executed, but not the ListChangeListener. Isn't this behaviour kind of inconsistent?

Michael

Edited by: 979705 on 05.01.2013 02:21

Edited by: 979705 on 05.01.2013 02:23

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points