为什么调用TreeViewer.refresh()不调用contentProvider的getChildren(Object)方法?

时间:2017-07-26 14:20:24

标签: eclipse jface

在其他地方,我看过herehere,但我没有找到答案。

一点背景:

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

基于this问题的信息:

  

如果您在树中添加或删除了对象,请使用

TreeViewer.refresh();
然后

refresh()(没有参数)应该通过模型中的新信息更新整个树。

通过在代码中设置断点,我发现在刷新过程中,框架在节点上多次调用hasChildren(),但从不调用getChildren()。

让我们说Project当前是打开的,并且在树中表示它的节点会扩展为一些子节点。我关闭项目并触发资源更改事件。这会导致refresh()。当被问到时,project现在从hasChildren()返回false,但是孩子们仍然在树中。

相反,如果项目已关闭且节点没有子节点(没有扩展箭头),打开项目将触发资源更改事件,refresh()树,项目节点返回true hasChildren()getChildren()从未被要求查明这些孩子是什么。该节点仍然没有子节点,也没有扩展箭头。

目前,模型会在添加新节点并删除旧节点时触发事件,并且树会侦听这些事件并根据需要在TreeViewer上调用add(Object, Object)remove(Object),但模型仅检查以查看是否需要通过内容提供商的getChildren()方法更改子项时更改其子项。

通过从getChildren()调用hasChildren()可以部分缓解这个问题,但这看起来很混乱,而且根据我对refresh()工作方式的理解,这不应该是必要的。

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

1 个答案:

答案 0 :(得分:1)

事实证明问题是传递给return Optional.ofNullable(obj) .map(optObj -> { try { myService.create(optObj); return new ResponseEntity<>("Operation successful", HttpStatus.CREATED); } catch (CustomException e) { return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); } }) .orElse(new ResponseEntity<>("Operation failed", HttpStatus.BAD_REQUEST)); 的{​​{1}}的实现如下所示:

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 } 方法,并且也应该处理这些方法。

在参数类无法识别的情况下悄悄地返回false是一个值得怀疑的举动,并且有问题的行可以替换为:

IElementComparer.equals(Object, Object)

我最终通过将调试器放入class org.eclipse.ui.internal.ViewSite

return ( one.equals( two ) ); <-- this will quietly handle unexpected classes better. 方法找到了这个