Подтвердить что ты не робот

ObservableList: как надежно обнаружить setAll?

В некоторых контекстах необходимо обнаружить - в ListChangeListener, без контроля над самим списком - "все данные обмениваются", f.i. когда нам нужно очистить какое-то состояние, например отбор - на совершенно новых данных старое состояние бессмысленно.

Полностью новые данные могут быть достигнуты с помощью

  • list.setAll(...)
  • list.set(otherObservableList), если list - ListProperty

Размышление о том, какой тип изменений может быть запущен на setAll (c - это изменение, элементы - это наблюдаемый список, псевдокод subChangeCount для подсчета подклассов):

// initially empty
assertEquals(0, items.size());
items.setAll(1, 2, 4);
assertEquals(1, c.subChangeCount());
assertTrue(c.wasAdded() && !c.wasReplaced());
assertEquals(0, c.getFrom());
assertEquals(c.getList().size(), c.getAddedSize()); 

// initially not empty
assertTrue(items.size() > 0);
items.setAll(1, 2, 4);
assertEquals(1, c.subChangeCount());
assertTrue(c.wasReplaced());
assertEquals(0, c.getFrom());
assertEquals(c.getList().size(), c.getAddedSize()); 

Это похоже на проверку утилиты:

boolean wasSetOrClearedAll(Change c) {
   if (c.getList().isEmpty()) return true;
   c.next();
   if (c.getAddedSize() == c.getList().size()) return true; 
   return false; 
}  

Напротив, внутренний код fx, f.i. при прослушивании элементов ComboBox:

while (c.next()) {
   comboBox.wasSetAllCalled = comboBox.previousItemCount == c.getRemovedSize();
   ... 
}
comboBox.previousItemCount = getItemCount();

хранит старый элемент item и сравнивает его с текущим removeSize (с которым мне неудобно, старое состояние слишком устарело слишком часто для моего вкуса), тем не менее есть хорошая вероятность, что я что-то упустил с помощью своего подхода.

Вопрос:

в каком контексте мой метод утилиты завершится неудачно (и основной подход будет правильно определять setAll)?

4b9b3361

Ответ 1

К сожалению, нет надежного способа обнаружения этого на стороне слушателя.

Борьба начинается с реализации по умолчанию, которая в основном выглядит следующим образом:

@Override
public boolean setAll(Collection<? extends E> col) {
    beginChange();
    try {
        clear();
        addAll(col);
    } finally {
        endChange();
    }
    return true;
}

Если вы передадите пустую коллекцию в setAll, результат и событие, которое запущено, будут точно такими же, как когда вы бы назвали clear.

Итак, ваш метод wasSetOrClearedAll возвращает true, когда был вызван clear (как и реализация ядра).

Итак, в конце нет общего обнаружения setAll, все зависит от вашего прецедента. Если вы можете сузить то, что вы пытаетесь обнаружить, вы можете написать для этого фильтр.