2017-07-26 97 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

相關問題