【问题标题】:ObservableList: how to reliably detect a setAll?ObservableList:如何可靠地检测 setAll?
【发布时间】:2015-01-15 16:12:06
【问题描述】:

在某些情况下,有必要检测 - 在 ListChangeListener 中,不受列表本身的控制 - “所有数据已换出”,f.i.当我们需要清除一些像选择这样的状态时——在全新的数据上,旧的状态是没有意义的。

可以通过以下方式获取全新的数据

  • list.setAll(...)
  • list.set(otherObservableList) 如果列表是 ListProperty

考虑可以在 setAll 上触发哪种类型的更改(c 是更改,items 是观察到的列表,“subChangeCount”伪代码用于计算子更改):

// initially empty
assertEquals(0, items.size());
items.setAll(1, 2, 4);
assertEquals(1, c.subChangeCount());
assertTrue(c.wasAdded() && !c.wasReplaced());
assertEquals(0, c.getFrom());
assertEquals(c.getList().size(), c.getAddedSize()); 

// initially not empty
assertTrue(items.size() > 0);
items.setAll(1, 2, 4);
assertEquals(1, c.subChangeCount());
assertTrue(c.wasReplaced());
assertEquals(0, c.getFrom());
assertEquals(c.getList().size(), c.getAddedSize()); 

这似乎允许进行实用程序检查,例如:

boolean wasSetOrClearedAll(Change c) {
   if (c.getList().isEmpty()) return true;
   c.next();
   if (c.getAddedSize() == c.getList().size()) return true; 
   return false; 
}  

相比之下,内部 fx 代码 f.i.在听 ComboBox 的项目:

while (c.next()) {
   comboBox.wasSetAllCalled = comboBox.previousItemCount == c.getRemovedSize();
   ... 
}
comboBox.previousItemCount = getItemCount();

存储旧的 itemCount 并将其与当前的 removedSize 进行比较(我对此感到不舒服,旧的状态对我的口味来说太陈旧了),但是我很可能在我的方法中遗漏了一些东西。

问题是:

我的实用程序方法会在哪种情况下失败(核心方法会正确检测到 setAll)?

【问题讨论】:

  • 您使用的 ObservableList 的具体类型是什么?看起来 ListProperty 是一个没有声明 setAll(...) 的抽象类
  • @zeki hmm .. 所有 ObservableLists 都必须有一个 setAll(T... item) - 当然可以不受支持,所以请采用任何已实现的(ListProperty 没什么特别的,它只是路由setAll 的后备列表)
  • 在这种情况下,您能否扩展 ListProperty 并在调用 super 方法之前让 setAll 触发事件?
  • @Zeki hmm .. 看起来我的问题并不太清楚(明天将尝试改写它:-) - 我的观点如果来自听众,只是看到变化而无法控制发件人.
  • @downvoter - 需要解释一下吗?

标签: java javafx javafx-8 observablelist


【解决方案1】:

不幸的是,在侦听器端没有可靠的方法检测到这一点。

斗争从默认实现开始,它大多看起来像这样:

@Override
public boolean setAll(Collection<? extends E> col) {
    beginChange();
    try {
        clear();
        addAll(col);
    } finally {
        endChange();
    }
    return true;
}

如果您将空集合传递给setAll,则结果和触发的事件都与您调用clear 时完全相同。

所以当clear 被调用时,您的方法wasSetOrClearedAll 也会返回true(核心实现也是如此)。

所以最终没有对setAll 的通用检测,这完全取决于您的用例。如果你可以缩小你想要检测的范围,你可以为此编写一个过滤器。

【讨论】:

  • ahhh ... 甚至没有考虑研究核心实现 ;-) 好论据,谢谢! clear/setAll 相同就足够了——基本上我需要一些方法来可靠地丢弃与旧项目相关的所有状态(没有对项目的引用,只对它们以前的位置进行引用)。嗯……回想一下
  • 而 ListChangeListener.Change.getRemoved() / getFrom() / getTo() 不够好清理?
  • hmm .. 如果我遵循 selectionModels 的核心实现,则不会。不过,这真是太糟糕了。可能需要从头开始思考,也许setAll毕竟不是这样的特例:-)
猜你喜欢
  • 2017-07-13
  • 1970-01-01
  • 2015-01-17
  • 2012-04-02
  • 2010-09-28
  • 1970-01-01
  • 2014-09-08
  • 2015-10-02
相关资源
最近更新 更多