2016-11-29 9 views
0

У меня есть довольно большое дерево в базе данных, загрузка всех элементов и добавление их в HierarchicalContainer при запуске выполняется плохо.
Вместо этого я хочу загрузить дочерние элементы дерева по клику.
Ну на самом деле немного раньше, так как я не areChildrenAllowed() или hasChildren(), чтобы вернуть неправильное значение.Как реализовать ленивое дерево загрузки в Ваадине?

Я надеялся найти что-то подобное в JFace TreeViewerITreeContentProvider.

Есть ли какой-либо пример или практика лучшей практики в этой теме?

Это то, что я до сих пор:

public class OutputNodeContainer extends HierarchicalContainer { 

    /** the view service */ 
    private IViewService service = CommonPlugin.getService(IViewService.class); 

    private List<Object> childrenRead = new ArrayList<>(); 

    @Override 
    public boolean areChildrenAllowed(Object itemId) { 
     if (!childrenRead.contains(itemId)) { 
      OutputNode node = (OutputNode) itemId; 
      List<OutputNode> children = service.getChildren(node.getNodeId(), false); 
      for (OutputNode child : children) { 
       addItem(child); 
       setParent(child, itemId); 
      } 
      childrenRead.add(itemId); 
      return !children.isEmpty(); 
     } 
     return super.areChildrenAllowed(itemId); 
    } 
} 

Но addItem(child); я бегу в это исключение:

java.lang.IllegalStateException: A connector should not be marked as dirty while a response is being written. 
     at com.vaadin.ui.ConnectorTracker.markDirty(ConnectorTracker.java:489) 
     at com.vaadin.server.AbstractClientConnector.markAsDirty(AbstractClientConnector.java:143) 
     at com.vaadin.ui.Tree.markAsDirty(Tree.java:348) 
     at com.vaadin.ui.AbstractSelect.fireItemSetChange(AbstractSelect.java:1746) 
     at com.vaadin.ui.AbstractSelect.containerItemSetChange(AbstractSelect.java:1713) 
     at com.vaadin.ui.Tree.containerItemSetChange(Tree.java:992) 
     at com.vaadin.data.util.AbstractContainer.fireItemSetChange(AbstractContainer.java:246) 
     at com.vaadin.data.util.HierarchicalContainer.fireItemSetChange(HierarchicalContainer.java:436) 
     at com.vaadin.data.util.IndexedContainer.fireItemSetChange(IndexedContainer.java:640) 
     at com.vaadin.data.util.HierarchicalContainer.enableAndFireContentsChangeEvents(HierarchicalContainer.java:460) 
     at com.vaadin.data.util.HierarchicalContainer.addItem(HierarchicalContainer.java:489) 
     at ch.scodi.vaadin.viewer.OutputNodeContainer.areChildrenAllowed(OutputNodeContainer.java:78) 
     at com.vaadin.ui.Tree.areChildrenAllowed(Tree.java:864) 
     at com.vaadin.ui.Tree.paintContent(Tree.java:732) 
     at com.vaadin.server.LegacyPaint.paint(LegacyPaint.java:65) 
     at com.vaadin.server.communication.LegacyUidlWriter.write(LegacyUidlWriter.java:82) 
     at com.vaadin.server.communication.UidlWriter.write(UidlWriter.java:143) 
     at com.vaadin.server.communication.UIInitHandler.getInitialUidl(UIInitHandler.java:284) 
     at com.vaadin.server.communication.UIInitHandler.synchronizedHandleRequest(UIInitHandler.java:80) 
     at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:41) 
     at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1422) 
     ... 63 common frames omitted 
+0

Не уверен, что, если он по-прежнему в силе для текущей реализации дерева: https://vaadin.com/forum/#!/thread/131803/131802 –

ответ

0

Даже если в Vaadin документации говорится отложенной загрузки для Tree является not supported, я удалось реализовать следующие ленивый loadingHierarchical интерфейс.

Это очень важно хранить все элементы в локальной структуре (в моем случае в HashMaphierarchy), не читают элементы несколько раз это не работает. Я думаю, потому что Ваадин не использует equals() и hashCode().

import java.util.Collection; 
import java.util.Collections; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 

import com.softmodeler.common.CommonPlugin; 
import com.softmodeler.model.OutputNode; 
import com.softmodeler.service.IViewService; 
import com.vaadin.data.Container.Hierarchical; 
import com.vaadin.data.Item; 
import com.vaadin.data.Property; 
import com.vaadin.data.util.BeanItem; 

/** 
* @author Flavio Donzé 
* @version 1.0 
*/ 
public class OutputNodeHierachical implements Hierarchical { 
    private static final long serialVersionUID = 8289589835030184018L; 

    /** the view service */ 
    private IViewService service = CommonPlugin.getService(IViewService.class); 

    /** collection of all root nodes */ 
    private List<OutputNode> rootNodes = null; 
    /** parent=>children mapping */ 
    private Map<OutputNode, List<OutputNode>> hierarchy = new HashMap<>(); 

    /** 
    * constructor 
    * 
    * @param rootNodes collection of all root nodes 
    */ 
    public OutputNodeHierachical(List<OutputNode> rootNodes) { 
     this.rootNodes = Collections.unmodifiableList(rootNodes); 

     addToHierarchy(rootNodes); 
    } 

    @Override 
    public Collection<?> getChildren(Object itemId) { 
     try { 
      List<OutputNode> children = hierarchy.get(itemId); 
      if (children == null) { 
       OutputNode node = (OutputNode) itemId; 
       children = service.getChildren(node.getNodeId(), false); 

       hierarchy.put(node, children); 

       // add children to hierarchy, their children will be added on click 
       addToHierarchy(children); 
      } 
      return children; 
     } catch (Exception e) { 
      VaadinUtil.handleException(e); 
     } 
     return null; 
    } 

    /** 
    * add each element to the hierarchy without their children hierarchy(child=>null) 
    * 
    * @param children elements to add 
    */ 
    private void addToHierarchy(List<OutputNode> children) { 
     for (OutputNode child : children) { 
      hierarchy.put(child, null); 
     } 
    } 

    @Override 
    public boolean areChildrenAllowed(Object itemId) { 
     return !((OutputNode) itemId).getChilds().isEmpty(); 
    } 

    @Override 
    public boolean hasChildren(Object itemId) { 
     return !((OutputNode) itemId).getChilds().isEmpty(); 
    } 

    @Override 
    public Object getParent(Object itemId) { 
     String parentId = ((OutputNode) itemId).getParentId(); 
     for (OutputNode node : hierarchy.keySet()) { 
      if (node.getNodeId().equals(parentId)) { 
       return node; 
      } 
     } 
     return null; 
    } 

    @Override 
    public Collection<?> rootItemIds() { 
     return rootNodes; 
    } 

    @Override 
    public boolean isRoot(Object itemId) { 
     return rootNodes.contains(itemId); 
    } 

    @Override 
    public Item getItem(Object itemId) { 
     return new BeanItem<OutputNode>((OutputNode) itemId); 
    } 

    @Override 
    public boolean containsId(Object itemId) { 
     return hierarchy.containsKey(itemId); 
    } 

    @Override 
    public Collection<?> getItemIds() { 
     return hierarchy.keySet(); 
    } 

    @Override 
    public int size() { 
     return hierarchy.size(); 
    } 

    @Override 
    public boolean setParent(Object itemId, Object newParentId) throws UnsupportedOperationException { 
     throw new UnsupportedOperationException(); 
    } 

    @Override 
    public boolean setChildrenAllowed(Object itemId, boolean areChildrenAllowed) throws UnsupportedOperationException { 
     throw new UnsupportedOperationException(); 
    } 

    @Override 
    public Item addItem(Object itemId) throws UnsupportedOperationException { 
     throw new UnsupportedOperationException(); 
    } 

    @Override 
    public Object addItem() throws UnsupportedOperationException { 
     throw new UnsupportedOperationException(); 
    } 

    @Override 
    public boolean removeItem(Object itemId) throws UnsupportedOperationException { 
     throw new UnsupportedOperationException(); 
    } 

    @Override 
    public boolean removeAllItems() throws UnsupportedOperationException { 
     throw new UnsupportedOperationException(); 
    } 

    @Override 
    public Class<?> getType(Object propertyId) { 
     throw new UnsupportedOperationException(); 
    } 

    @Override 
    public Collection<?> getContainerPropertyIds() { 
     throw new UnsupportedOperationException(); 
    } 

    @Override 
    public Property<?> getContainerProperty(Object itemId, Object propertyId) { 
     throw new UnsupportedOperationException(); 
    } 

    @Override 
    public boolean addContainerProperty(Object propertyId, Class<?> type, Object defaultValue) throws UnsupportedOperationException { 
     throw new UnsupportedOperationException(); 
    } 

    @Override 
    public boolean removeContainerProperty(Object propertyId) throws UnsupportedOperationException { 
     throw new UnsupportedOperationException(); 
    } 

} 

Добавление контейнера к Tree, как это:

OutputNodeHierachical dataSource = new OutputNodeHierachical(rootNodes); 

Tree mainTree = new Tree(); 
mainTree.setSizeFull(); 
mainTree.setContainerDataSource(dataSource); 
mainTree.addItemClickListener(new ItemClickListener() { 
    private static final long serialVersionUID = -413371711541672605L; 

    @Override 
    public void itemClick(ItemClickEvent event) { 
     OutputNode node = (OutputNode) event.getItemId(); 
     openObject(node.getObjectId()); 
    } 
}); 

 Смежные вопросы

  • Нет связанных вопросов^_^