ListChangeListener.Change: how to properly handle updated and permutated items
Asked Answered
L

1

7

From the JavaDoc:

ObservableList theList = ...;

 theList.addListener(new ListChangeListener<Item>() {
     public void onChanged(Change<tem> c) {
         while (c.next()) {
             if (c.wasPermutated()) {
                     for (int i = c.getFrom(); i < c.getTo(); ++i) {
                          //permutate
                     }
                 } else if (c.wasUpdated()) {
                          //update item
                 } else {
                     for (Item remitem : c.getRemoved()) {
                         remitem.remove(Outer.this);
                     }
                     for (Item additem : c.getAddedSubList()) {
                         additem.add(Outer.this);
                     }
                 }
             }
         }
     });
 }

Adding and removing items is straight forward, but what about //update item and // permutate?

How do I know which items have been permutated by which other items?

What does update mean exactly? Is it just adding the same item to the list again?

And what about

for (Item remitem : c.getRemoved()) {
remitem.remove(Outer.this);
}
or (Item additem : c.getAddedSubList()) {
additem.add(Outer.this);
}

What does Outer.this mean?

Lepus answered 9/2, 2017 at 11:1 Comment(0)
S
6

How do I know which items have been permutated by which other items?

The change has a getPermutation() method that describes how the elements were permuted.


What does update mean exactly?

A list is updated if properties belonging to an element change, though the same elements remain in the list (in the same order). For example, given a class

public class Item {

    private final IntegerProperty value = new SimpleIntegerProperty();

    public final IntegerProperty valueProperty() {
        return value ;
    }

    public final int getValue() {
        return valueProperty().get();
    }

    public final void setValue(int value) {
        valueProperty().set(value);
    }

    public Item(int value) {
        setValue(value);
    }
}

calling setValue() on an element of the list may fire an update. Note that the documentation states that updates are "optional" and may not be fired by all lists. Specifically, to obtain a list that fires updates, create it with an extractor:

ObservableList<Item> list = FXCollections.observableArrayList(
    item -> new Observable[] {item.valueProperty()});

list.addAll(new Item(1), new Item(2), new Item(3));

list.addListener((Change<? extends Item> c) -> {
    while (c.next()) {
        if (c.wasUpdated()) {
            System.out.println("Items from "+c.getFrom()+" to "+c.getTo()+" changed");
        }
    }
});

list.get(1).setValue(42);

The last line of code doesn't change which elements are in the list, or which order they are in, but changes a property of one of the elements. So this change will fire an update.


What does Outer.this mean?

It is simply a reference to the current object of the surrounding class (which is assumed to have class name Outer); i.e. not the current object of the anonymous inner class implementation of ListChangeListener. See What is the difference between Class.this and this in Java (and many others). I think the context for the code snippet in the documentation is supposed to be a class that implements ObservableList and maintains its own ObservableList instance (decorator pattern). It observes the list instance and updates itself to keep in sync with it.

Shaman answered 9/2, 2017 at 11:32 Comment(2)
Many thanks for the explanations! One more question regarding Outer.this. Should the code not be Outer.this.remove(remitem) and Outer.this.add(additem) intead?Lepus
I guess in my interpretation the code you suggest would be more intuitive. Perhaps the idea is that the surrounding class (Outer) is some kind of listener, and the code is registering/deregistering the listener to items that are added and removed. Not exactly sure what the intention was in the documentation.Shaman

© 2022 - 2024 — McMap. All rights reserved.