为了将不可变的可观察列表返回给我的API客户端,我使用了FXCollections.unmodifiableObservableList(list)包装器,如下所示:

private final ObservableList<Person> persons = FXCollections.observableArrayList();

public ObservableList<Person> getPersons() {
    return FXCollections.unmodifiableObservableList(persons);
}

但是,当客户端将ListChangeListener添加到返回的列表时,发生更改时不会收到通知。显然,这是因为FXCollections类创建的包装器在包装的列表上设置了一个弱监听器,并且该弱监听器被垃圾回收了。

我有没有想过关于这个包装纸的东西?

返回不可变的可观察列表的正确方法是什么?

最佳答案

您处在正确的轨道上:包装器列表向包装器列表添加了一个弱侦听器,以避免内存泄漏,如果您不持有对包装器列表的引用,则会对其进行垃圾回收。

查看此测试(取自here):

private ObservableList<String> s = FXCollections.observableArrayList();

@Override
public void init() throws Exception {
    FXCollections.unmodifiableObservableList(s).addListener((ListChangeListener.Change<? extends String> c) ->
        System.out.println(c));
    s.setAll("A1");
    s.setAll("A2");
    System.gc();
    s.setAll("A3"); // <- Doesn't trigger the listener
}

它打印:
{ [A1] added at 0 }
{ [A1] replaced by [A2] at 0 }

但是,如果您添加对列表的引用:
private ObservableList<String> s = FXCollections.observableArrayList();

@Override
public void init() throws Exception {
    // create a reference
    final ObservableList<String> wrapperList = FXCollections.unmodifiableObservableList(s);

    wrapperList.addListener((ListChangeListener.Change<? extends String> c) ->
        System.out.println(c));
    s.setAll("A1");
    s.setAll("A2");
    System.gc();
    s.setAll("A3"); // <- Triggers the listener
}

现在打印:
{ [A1] added at 0 }
{ [A1] replaced by [A2] at 0 }
{ [A2] replaced by [A3] at 0 }

09-28 14:19