我正在使用 Vaadin 构建一个 Web 应用程序,其中一个功能需要一个树来显示元素,问题是这个树加载了多达(40K)个项目甚至更多。
在几千个项目的级别上,Vaadin 树是可以接受的,但现在不是,它正在减慢 Web 浏览器中的所有内容。
我想到的是对 Web 服务器和 Web 客户端之间的负载进行分页,并显示几个在用户滚动树时更新的项目,问题是我不知道从哪里开始,即使这是否适用。
这是一个好方法吗?有更好的吗?为一张桌子放弃一棵树不是解决方案,客户不想这样做。
我建议您在这种情况下使用TreeTable
而不是。Tree
它从服务器延迟加载行到客户端,因此不会减慢浏览器的速度。
您可以在扩展树的节点时通过动态添加子节点来延迟加载树的内容。我多次使用的方法的基本思想是,
final Tree tree = new Tree();
//get the top level collection of entities
Collection<MyEntity> myEntitiesCategories = findEntities(MyEntity.class);//findEntities is one of your method that retrieves entities from a datasource
for (MyEntity myEntity : myEntitiesCategories) {
tree.addItem(myEntity);
}
tree.addListener(new Tree.ExpandListener() {
@Override
public void nodeExpand(ExpandEvent event) {
MyEntity myEntityCategory = (MyEntity) event.getItemId();
Collection<MyEntity> myEntities = myEntityCategory.getChildrenMyEntities();
for (MyEntity myEntity : myEntities) {
tree.addItem(myEntity);
tree.setParent(myEntity, myEntityCategory);
tree.setChildrenAllowed(myEntity, false);//the boolean value could also be true, it depends on whether it can have children or not
}
}
});
As far as I know Tree
component does not support built-in lazy loading (which would be the most convenient for all of us).
One approach would be to:
Collapsible
container as a data sourceTree.ExpandListener
Here you can find an example of using Tree.ExpandListener.
Here you can find an example implementation of Collapsible container.
I hope it helps.
尽管在 Vaadin 文档Tree
中说不支持延迟加载,但我还是设法实现了以下延迟加载 Hierarchical
接口。
将所有元素存储在本地结构中非常重要(在我的例子中HashMap
hierarchy
),不要多次读取元素,这是行不通的。我认为是因为 Vaadin 不使用equals()
and 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());
}
});
我希望这个例子对其他人有帮助,因为我没有在互联网上找到一个真实的例子。