通知 。可观察属性的变化

Notify . change of ObservableProperties

我有一个 class 具有以下属性:

public class Member {
    private LongProperty version;

    private LongProperty id;

    private StringProperty name;

    private StringProperty surname;

    private StringProperty bornname;

    private StringProperty photo;

    private ObjectProperty<Age> age;

    private ObjectProperty<Sex> sex;
}

问题是,当我在此对象上添加 Change Listener 时:

{
    private ObjectProperty<Member> member;

    public void addMemberChangeListener() {
        this.member.addListener((observable, oldValue, newValue) -> {
            if (newValue != null) {
                (...)
      }
    }
}

当我更改属性值时,更改侦听器没有得到通知。还有其他方法可以通知侦听器有关实现标准观察者模式的更改属性吗?

属性侦听器在更改值 memberProperty.setValue(otherMember) 时触发,而不是在您修改其值 memberProperty.getValue().setId(0)

的某些 属性 时触发

尝试使用 PropertyChangeSupport.

示例:

public class Member
{

    private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);

    private long id;
    private String name;

    public void addChangeListener(PropertyChangeListener listener)
    {
        this.pcs.addPropertyChangeListener(listener);
    }

    public void removeChangeListener(PropertyChangeListener listener)
    {
        this.pcs.removePropertyChangeListener(listener);
    }

    public void setId(long newId)
    {
        long oldId = this.id;
        this.id = newId;
        pcs.firePropertyChange("id", oldId, newId);
    }

    public void setName(String newName)
    {
        String oldName = this.name;
        this.name = newName;
        pcs.firePropertyChange("name", oldName, newName);
    }

}

使用:

Member member = new Member();

member.addChangeListener((evt) ->
{
    System.out.println("Changed "
            + evt.getPropertyName()
            + ": " + evt.getOldValue()
            + " -> " + evt.getNewValue());
});

member.setId(15);
member.setName("Maria");
member.setName("Ana");

输出:

Changed id: 0 -> 15
Changed name: null -> Maria
Changed name: Maria -> Ana

如果您想添加一个监听器,当属于 Member 的一个实例的任何属性发生变化时收到通知,您可以执行如下操作:

Member member = new Member();

ChangeListener<Object> listener = (obs, oldValue, newValue) -> 
    System.out.println(obs + " changed from " + oldValue + " to " + newValue);

Stream.of(member.versionProperty(), member.idProperty(), member.nameProperty() /*, ... */)
    .forEach(p -> p.addListener(listener));

请注意,具体的 属性 类 包含一个构造函数,该构造函数采用拥有的 bean 和 属性 的名称,因此如果您想支持这种使用,您可能想使用那些构造函数:

public class Member {

    private final LongProperty version = new SimpleLongProperty(this, "version");
    private final StringProperty name = new SimpleStringProperty(this, "name");

    // ...
}

然后您可以在更改侦听器中利用它:

ChangeListener<Object> listener = (obs, oldValue, newValue) -> 
    System.out.println(((Property<?>)obs).getName() + " changed from " + oldValue + " to " + newValue);

只是评论:根据我的经验,很少(充其量)需要它。您通常(总是?)会发现为每个 属性 注册不同的侦听器更方便,因为通常 属性 更改时要采取的操作取决于哪个 属性 发生更改。在其他情况下,无论如何通常都有更优雅的解决方案。