Issue
What is the correct change order?
In the documentation here - click, we can see the following example:
ObservableList<Item> theList = ...;
theList.addListener(new ListChangeListener<Item>() {
public void onChanged(Change<Item> 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);
}
}
}
});
}
BUT below the sample code there is:
Note: in case the change contains multiple changes of different type, these changes must be in the following order: permutation change(s), add or remove changes, update changes. This is because permutation changes cannot go after add/remove changes as they would change the position of added elements. And on the other hand, update changes must go after add/remove changes because they refer with their indexes to the current state of the list, which means with all add/remove changes applied.
Is the example wrong then? Or maybe I'm missing something?
Solution
There are three types of changes that can be fired by an ObservableList
:
- Permutation (a change in order)
- Addition/removal (or replacement, which is just a simultaneous addition and removal)
- An update (a change in an element's property, requires an "extractor")
A single change can be only one of those types. However, a single Change
instance can carry multiple changes. That's why you have to iterate over the Change
instance by calling next()
in a while
loop.
The documentation you quote:
Note: in case the change contains multiple changes of different type, these changes must be in the following order: permutation change(s), add or remove changes, update changes.
Is regarding the order of changes returned by said next()
method. Here the order is important because the Change
must report the list as it currently exists.
That documentation does not dictate the order you query the type of change. If the change was not a permutation then c.wasPermutated()
simply returns false
and the code moves on. Same with the other types of changes. Note that, because of how the API is designed, if a change is neither a permutation nor an update then it must be an addition or removal (or replacement).
So the example is not wrong. If you wanted you could write it as:
while (c.next()) {
if (c.wasPermutated()) {
// process perumutation
} else if (c.wasRemoved() || c.wasAdded()) {
// process removal, addition, or replacement
} else {
// process update
}
}
But that does not change the behavior of the code.
Answered By - Slaw