Почему наблюдаемый список не всегда замечает изменения? - PullRequest
0 голосов
/ 29 мая 2019

У меня есть код, который я не понимаю, результат:

ObservableList<Integer> li = FXCollections.observableArrayList();
        li.add(1);
        li.add(2);
        IntegerProperty intProp = new SimpleIntegerProperty(5);

        li.add(intProp.getValue());

        li.add(li.get(0) + li.get(2));
        System.out.println(li);
        li.addListener((ListChangeListener<Integer>) change -> {
            li.set(3, li.get(0) + li.get(2));
        });
        intProp.setValue(3);
        System.out.println(intProp.get());
        System.out.println(li.get(2));
        System.out.println(li);

Я не понимаю, почему изменяющееся значение intProp не влияет на observableList, я имею в виду, что int в позиции 2 должен быть значением свойства, поэтому второй и третий sysout должны совпадать, а первый должен отличаться от предыдущего, но это не так, и это дает мне:

[1, 2, 5, 6]
3
5
[1, 2, 5, 6]

Я попытался внести некоторые изменения, написав это:

        ObservableList<Integer> li = FXCollections.observableArrayList();
        li.add(1);
        li.add(2);

        li.add(5);

        li.add(li.get(0) + li.get(2));
        System.out.println(li);
        li.addListener((ListChangeListener<Integer>) change -> {
            li.set(3, li.get(0) + li.get(2));
        });
        li.set(2, 3);
        System.out.println(li);

это, очевидно, работает, но дает много ошибок, которые я не понимаю.

Спасибо!

1 Ответ

1 голос
/ 29 мая 2019

На фундаментальном уровне вы, похоже, ожидаете следующего:

IntegerProperty property = new SimpleIntegerProperty(5);
int i = property.get();
property.set(10);
System.out.println(i);

Чтобы распечатать 10 вместо 5.Это не может произойти в Java, потому что Java всегда передача по значению .То же самое верно при добавлении значения к ObservableList;все, что вы сделали, взяли значение свойства в момент и добавили его в список.После этого свойство и список являются полностью отдельными объектами.

Нет фундаментального способа наблюдать переменные для изменений в Java.Чтобы получать уведомления об изменениях, должен существовать код, который реализует это поведение.IntegerProperty - это просто оболочка вокруг int, которая перехватывает код, изменяющий значение, и уведомляет наблюдателей об изменении.Что-то вроде:

public void set(int newValue) {
    this.value = newValue;
    notifyObservers();
}

Примечание. Реальная реализация IntegerProperty более сложна, чем эта.

То же самое относится и к ObservableList.Все основные реализации - это просто обертки вокруг обычного List, а ObservableList просто перехватывает вызовы и уведомляет наблюдателей об изменениях.Вот почему, если вы оберните свой собственный List с помощью FXCollections.observableList(List), вы больше не сможете напрямую изменять List, потому что это обходит обтекание ObservableList и, таким образом, никакие события изменения не будут запущены.

Если вы хотите, чтобы ObservableList обновлялся при изменении IntegerProperty, вам необходимо добавить прослушиватель к IntegerProperty, который соответствующим образом обновит ObservableList.Если вы хотите знать об изменениях содержащихся элементов через ObservableList, вам нужно использовать экстрактор - см. этот ответ .


это, очевидно, работает, но дает много ошибок, которые я не понимаю.

Игнорирование противоречия между ", очевидно, работает " и " дает мне много ошибок", на самом деле вы не предоставляете ошибки, которые получаете.Без ошибок трудно понять, что происходит не так.Однако у вас есть следующее (что может или не может быть связано с вашими ошибками):

li.addListener((ListChangeListener<Integer>) change -> {
    li.set(3, li.get(0) + li.get(2));
});

Это изменение ObservableList, вызвавшее событие изменения.Вы не должны этого делать :

Предупреждение: Этот класс напрямую обращается к списку источников для получения информации об изменениях.
Это эффективно делаетИзменение объекта недействительным, когда в списке происходит другое изменение.
По этой причине небезопасно использовать этот класс в другом потоке.
Это также означает, что список источников не может бытьизменен внутри слушателя , так как это сделает недействительным этот объект Change для всех последующих слушателей.

...