Как логическое свойство работает с createBooleanBinding - PullRequest
0 голосов
/ 20 мая 2019

У меня есть этот код:

public class Test {
    public static void main(String [] args) {

        ObservableList<Integer> l = FXCollections.observableArrayList();
        l.add(1);
        l.add(2);
        l.add(3);
        BooleanProperty isPlayable = new SimpleBooleanProperty();
        isPlayable.bind(Bindings.createBooleanBinding(() -> 
        {
            System.out.println("List has changed");

            return l.contains(2);
        },l
        ));
l.remove(1);

Я не понимаю, почему этот код отображал «Список изменился» только один раз? Он должен дважды, один в привязке, а затем в удалении, потому что список можно наблюдать. Почему изменение списка не влияет на логическое свойство?

(У меня большая проблема в длинном коде, но эта ситуация иллюстрирует мое недопонимание привязок логических свойств)

Спасибо!

1 Ответ

2 голосов
/ 20 мая 2019

Из документации из ObservableValue (которая наследуется от Binding и Property):

Реализация ObservableValue может поддерживать отложенную оценку,Это означает, что значение не пересчитывается сразу после изменений, а лениво при следующем запросе значения.Все привязки и свойства в этой библиотеке поддерживают отложенную оценку.

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

Реализации этого класса должны стремиться генерировать как можно меньше событий, чтобы не тратить слишком много времени на обработчики событий.,Реализации в этой библиотеке помечают себя как недействительные, когда происходит первое событие недействительности.Они больше не генерируют события аннулирования до тех пор, пока их значение не будет пересчитано и снова станет действительным.

Два типа слушателей могут быть присоединены к ObservableValue: InvalidationListener для прослушивания событий аннулирования и ChangeListener для прослушиваниясобытия изменения.

Важное примечание: добавление ChangeListener приводит к принудительным вычислениям, даже если реализация ObservableValue поддерживает отложенную оценку.

Обратите внимание, что оба Property#bind и Bindings#createXXXBinding регистрируют InvalidationListener на зависимости / зависимостях, а не ChangeListener.

Как видите, привязки и свойства в ядре JavaFX ленивы.Вы никогда не запрашиваете значение после удаления элемента из ObservableList, поэтому значение никогда не пересчитывается.Поскольку значение никогда не пересчитывается, ваш Callable не вызывается во второй раз.

Я был действительно удивлен, что вы видели "List has changed" даже один раз.Ни один из вашего кода не запрашивает значение, поэтому я не ожидал, что значение будет вычислено.Однако, глядя на реализацию, похоже, что акт регистрации InvalidationListener вызывает проверку ObservableValue (т. Е. Значение запрашивается) - и #bind добавляет InvalidationListener.Я не уверен, почему реализация делает это, но это делает.

...