为了将不可变的可观察列表返回给我的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 }