FXCollections.unmodifiableObservableList的目的是什么?

时间:2017-06-03 07:13:24

标签: java javafx javafx-8

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

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

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

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

我是否想念这个包装器?

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

2 个答案:

答案 0 :(得分:4)

你走在正确的轨道上:包装器列表为包装列表添加了一个弱侦听器,以避免内存泄漏,如果你没有保存对包装器列表的引用,它将被垃圾收集。

参见此测试(取自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 }

答案 1 :(得分:1)

作为参考,我profiled下面的(有点人为的)例子虽然有几个周期性的和forced垃圾收集周期没有任何不合适的东西 - 只有一个小的,世俗的,向上的趋势作为{{1的实例累积。添加到支持列表中的WeakListChangeListenerprivate implementation保留。当侦听器变为Integer并且无法再将更改转发到不可修改列表的侦听器时,弱侦听器将从备份列表中removed。如果客户端的侦听器停止看到更改,您可能需要查看客户端如何管理null返回的列表。

附录:正如WeakListChangeListener API中的注释和{JoséPereda的here所述,“您必须保留对传入的getPersons()的引用,只要它在使用,否则将很快收集垃圾。“

ListChangeListener

profile

changed { [0] added at 0 }
…
changed { [2162] added at 2162 }