Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 721
kerner1000 Avatar asked Feb 09 '17 11:02

kerner1000


1 Answers

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.

like image 73
James_D Avatar answered Sep 21 '22 10:09

James_D