2017-07-26 81 views
0

在其他地方,我看了herehere,但我还没有找到我的问题的答案。为什么调用TreeViewer.refresh()不会调用contentProvider的getChildren(Object)方法?

一点背景:

  • 我执行代表的资源在Eclipse项目的一个子集的视图。
  • 树中的项目节点将检查项目是否已打开,以查看它们是否应包含子项。实际上,项目节点的hasChildren()方法返回IProject.isOpen()
  • eclipse视图订阅resourceChangeEvents,并且在发生任何更改的情况下,它会在TreeViewer上调用refresh()

基于从this问题的资料:

如果您添加或删除树中的对象使用

TreeViewer.refresh(); 

refresh()(不带参数)应再使用模型中的新信息通过并更新整个树。


通过在代码中设置断点,我发现,在刷新过程中,该框架调用hasChildren()节点上几次,但从来没有电话的getChildren()。

我们假设Project当前处于打开状态,并且树中代表它的节点已经扩展了一些子节点。我关闭了项目并且资源更改事件被触发。这导致refresh()。当被问及时,project现在从hasChildren()返回错误,但孩子们仍然存在于树中。相反,如果项目已关闭且节点没有子项(没有展开箭头),则打开该项目将触发资源更改事件,其中refresh()位于树中,项目节点将从hasChildren()返回true,但仍然会从hasChildren()返回true getChildren()永远不会被称为找出这些孩子是什么。该节点仍然没有子节点并且没有展开箭头。

目前的模型触发事件时添加新的节点,并删除旧,和树监听这些和对TreeViewer中适当地调用add(Object, Object)remove(Object),但该模型只检查,看看它的孩子是否需要改变当通过内容提供者的getChildren()方法询问他们时。

通过从hasChildren()调用getChildren()可以部分缓解该问题,但这看起来很麻烦,而且从我对refresh()的工作原理的理解来看,这不是必须的。


为什么TreeViewer中的refresh()方法不会重新查询节点,看看它的孩子们?鉴于这是不这样做,它是如何处理添加和删除对象?

+0

它只调用getChildren如果节点被展开。它应该只显示来自hasChildren值的展开/折叠指标。 –

+0

@greg:这就是我期望发生的事情。但是,尽管有'refresh',展开/折叠指示符并不反映从'hasChildren'返回的值。 –

+0

也许您应该向我们展示您的内容提供商的实施情况,并准确指出设置为查看者的输入内容。 – nitind

回答

0

原来的问题是,IElementComparer传递给TreeViewer.setComparer的实现是这样的:

@Override 
public boolean equals(final Object one, final Object two) { 
    if (one.getClass().equals(two.getClass())) { <-- This is not always true... 
     if (one instanceof MyCustomNodeBaseClass) { 
      return ((MyCustomNodeBaseClass) one).isEquivalentTo((MyCustomNodeBaseClass) two); 
     } 
    } 
    return false; <-- ...therefore this is the problem, as it wasn't expected to be reached 
} 

IElementComparer.equals(Object, Object)方法可以与class org.eclipse.ui.internal.ViewSite参数调用,并且应该处理这些呢。

这是一个可疑的举动在情况下,类的参数是无法识别的悄然返回false,而问题的行可以替换为:

return (one.equals(two)); <-- this will quietly handle unexpected classes better. 

我终于找到这个按照调试器进入updatePlus()方法的AbstractTreeViewer

相关问题