Как наследовать от ObservableValue? - PullRequest
0 голосов
/ 11 июня 2018

У меня есть класс, который содержит различные свойства:

public class Foo extends ??? {
    public SimpleBooleanProperty prop1 = new SimpleBooleanProperty();
    public SimpleStringProperty prop2 = new SimpleStringProperty();

    // ** more properties ** //
}

В большинстве случаев все свойства меняются, и для некоторых слушателей было бы намного проще получить только один обратный вызов, вызванный при изменении любого свойства изатем получить значения всех свойств (даже если не все они изменены).Какой класс я должен построить?

Я хотел бы зарегистрировать слушателя с чем-то вроде

Foo foo = new Foo();
foo.addListener( new ChangeListener< >() {
      void onChange(Foo newValue,Foo oldValue) {
           System.out.println(String.valueOf(newValue.prop1.get());
           System.out.println(String.valueOf(newValue.prop2.get());
      });

Печать на консоль - это только пример, дело в том, что слушателю нужно только знать, что что-то изменилосьи это хорошо, чтобы позвонить добытчикам.Я немного растерялся, с чего начать.Существует интерфейс Observable и огромное количество различных базовых классов (например, ObservableValueBase<T> или SimpleObjectProperty<T>).Какой из них я должен наследовать от / расширить?

Ответы [ 2 ]

0 голосов
/ 12 июня 2018

Не совсем уверен, правильно ли я истолковал, что вам нужно.Вероятно, это то, что вам нужно:

public class Foo extends ??? {
    public SimpleBooleanProperty prop1 = new SimpleBooleanProperty();
    public SimpleStringProperty prop2 = new SimpleStringProperty();

    // ** more properties ** //

    private final ObjectBinding<Void> binding = Bindings.createObjectBinding(this::bar, prop1, prop2, prop3, prop4);

    private final Void bar() {
        Optional.of(newValue.prop1.get()).ifPresent(System.out::println);
        Optional.of(newValue.prop2.get()).ifPresent(System.out::println);
        Optional.of(newValue.prop3.get()).ifPresent(System.out::println);
        Optional.of(newValue.prop4.get()).ifPresent(System.out::println);

        return null;
    }
}

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

0 голосов
/ 11 июня 2018

Реализация ObservableValue<Foo>, как предполагает ваш слушатель, будет означать, что ваш объект оборачивает Foo объект, что явно не так.

Для ObservableValue будут классы для расширения.Для Observable такого класса не существует, и вы должны реализовать интерфейс самостоятельно.Это можно сделать, добавив / удалив прослушиватели во все свойства Observable, но для эффективности я рекомендую реализовать это с одним прослушивателем для каждого свойства:

public abstract class ObservableBase implements Observable {

    private final List<InvalidationListener> listeners = new ArrayList<>();

    protected ObservableBase(Observable... dependencies) {
        InvalidationListener listener = o -> {
            for (InvalidationListener l : listeners) {
                try {
                    l.invalidated(o);
                } catch (RuntimeException ex) {
                    ex.printStackTrace();
                }
            }
        };
        for (Observable o : dependencies) {
            o.addListener(listener);
        }
    }

    @Override
    public final void addListener(InvalidationListener listener) {
         Objects.requireNonNull(listener);
         listeners.add(listener);
    }

    @Override
    public final void removeListener(InvalidationListener listener) {
         listeners.remove(listener);
    }
}
public class Foo extends ObservableBase {
    public final BooleanProperty prop1;
    public final StringProperty prop2;

    // ** more properties ** //

    private Foo(BooleanProperty prop1, StringProperty prop2) {
        super(prop1, prop2);
        this.prop1 = prop1;
        this.prop2 = prop2;
    }

    public Foo() {
        this(new SimpleBooleanProperty(this, "prop1"), new SimpleStringProperty(this, "prop2"));
    }
}
Foo foo = new Foo();
InvalidationListener l = o -> {
    ReadOnlyProperty p = (ReadOnlyProperty) o;
    System.out.println("changed property: " + p.getName());

    Foo bean = (Foo) p.getBean();

    System.out.println(bean.prop1.get());
    System.out.println(bean.prop2.get());
};
foo.addListener(l);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...