为什么调用TreeViewer.refresh()不调用contentProvider的getChildren(Object)方法? [英] Why does calling TreeViewer.refresh() not call the contentProvider's getChildren(Object) method?

查看:202
本文介绍了为什么调用TreeViewer.refresh()不调用contentProvider的getChildren(Object)方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

其他地方,我已经看过这里此处,但我没有找到答案我的问题。



一点背景:




  • 我正在实现一个视图这表示eclipse项目中的资源的一个子集。

  • 树中的项目节点将检查项目是否打开以查看其是否应包含子项。有效地,项目节点的 hasChildren()方法返回 IProject.isOpen()

  • eclipse视图订阅resourceChangeEvents,并且在发生任何更改的情况下,它会调用TreeViewer上的 refresh() li>





根据这个问题:


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

  TreeViewer.refresh(); 


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






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



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



相反,如果项目关闭,节点没有孩子(没有扩展箭头),打开项目将触发资源更改事件,其中 refresh() es树,项目节点从 hasChildren()然后 getChildren()返回true, 从来没有被调用来查找这些孩子是什么。节点仍然没有子节点,没有扩展箭头。



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



通过调用可以部分缓解此问题。 getChildren() from hasChildren(),但这似乎很混乱,从我对refresh()的理解的理解不是必须的。






为什么TreeViewer的 refresh()查询节点以查看其子节点?既然没有这样做,那么它是如何处理添加和删除对象的呢?

解决方案

就是将 IElementComparer 传递给 TreeViewer.setComparer 的实现如下所示:

  @Override 
public boolean equals(final Object one,final Object two){
if(one.getClass()。equals .getClass())){< - 这不总是真的...
如果(一个实例MyCustomNodeBaseClass){
返回((MyCustomNodeBaseClass)).isEquivalentTo((MyCustomNodeBaseClass)两);
}
}
return false;因此,这是一个问题,因为预计不会达到
}

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



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

  return(one.equals(two)); <  - 这将安静地处理意外的类更好。 

我最终通过将调试器跟踪到$ code> updatePlus() code>方法 AbstractTreeViewer


Amongst other places, I've looked here and here, but I've not found an answer to my question.

A little background:

  • I'm implementing a view that represents a subset of the resources in an eclipse project.
  • The project nodes in the tree will check whether the project is open to see if they should contain children. Effectively, the Project node's hasChildren() method returns IProject.isOpen().
  • The eclipse view subscribes to resourceChangeEvents, and in the case that any change occurs, it calls refresh() on the TreeViewer.

Based on information from this question:

If you have added or removed objects in the tree use

TreeViewer.refresh();

refresh() (with no arguments) should then go through and update the entire tree with fresh information from the model.


By setting breakpoints in the code, I've discovered that during the refresh process, the framework calls hasChildren() several times on a node, but never calls getChildren().

Let us say that Project is currently open, and the node representing it in the tree is expanded with some children. I close the project and resource change event is fired. This causes a refresh(). When asked, the project now returns false from hasChildren(), and yet the children are still present in the tree.

Conversely, if the project is closed and the node has no children (there is no expansion arrow), opening the project will fire a resource change event, which refresh()es the tree, the project node returns true from hasChildren() and yet getChildren() is never called to find out what these children are. The node still has no children and no expansion arrow.

Currently the model fires events when new nodes are added and old ones removed, and the tree listens for these and calls add(Object, Object) and remove(Object) on the TreeViewer as appropriate, but the model only checks to see whether its children need to be changed when it is asked for them via the content provider's getChildren() method.

The problem can be partially alleviated by calling getChildren() from hasChildren(), but this seems messy, and from my understanding of how refresh() works, shouldn't be necessary.


Why does the TreeViewer's refresh() method not re-query a node to see what its children are? Given that is doesn't do this, how is it meant to handle adding and removing objects?

解决方案

It turns out the problem was that the Implementation of the IElementComparer passed to TreeViewer.setComparer looked like this:

@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
}

The IElementComparer.equals(Object, Object) method can be called with arguments of class org.eclipse.ui.internal.ViewSite, and should handle those too.

It was a questionable move to quietly return false in cases where the class of the parameters was unrecognised, and the problematic line could be replaced with:

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

I eventually found this by following the debugger into the updatePlus() method of the AbstractTreeViewer

这篇关于为什么调用TreeViewer.refresh()不调用contentProvider的getChildren(Object)方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆