如何通过事件总线告知GWT单元格小部件数据是否已更改?

Cas*_*dan 6 gwt event-bus

我有一个GWT单元树,用于显示CMS的文件结构.我正在使用AsyncDataProvider从我创建的自定义RPC类加载数据.我还有一个Web Socket系统,它将从也在系统中工作的其他客户端广播事件(文件创建,重命名,移动,删除等).

我想要解决的是当我收到其中一个事件时,我如何正确更新我的Cell Tree?

我想这个问题类似于在页面上有两个我的Cell Tree实例,它们呈现相同的服务器端数据,并希望确保当用户更新一个时,另一个更新也通过使用EventBus.

我觉得这应该很简单,但我现在花了大约6个小时才没有进展.我的代码包含在下面:

注意:我没有使用RequestFactory,即使它看起来像我是我的自定义RPC框架.此外,FileEntity只是一个文件的简单表示,其名称可以访问getName().

private void drawTree() {

        // fileService is injected earlier on and is my own custom rpc service
        TreeViewModel model = new CustomTreeModel(new FileDataProvider(fileService));
        CellTree tree = new CellTree(model, "Root");

        tree.setAnimationEnabled(true);

        getView().getWorkspace().add(tree);

    }

    private static class CustomTreeModel implements TreeViewModel {

        // I am trying to use a single AsyncDataProvider so I have a single point of loading data which I can manipulate (Not sure if this is the correct way to go)
        public CustomTreeModel(FileDataProvider dataProvider) {
            this.provider = provider;
        }


        public <T> NodeInfo<?> getNodeInfo(final T value) {

            if (!(value instanceof FileEntity)) {

                                // I already have the root File loaded in my presenter, if we are at the root of the tree, I just add it via a list here
                ListDataProvider<FileEntity> dataProvider = new ListDataProvider<FileEntity>();

                dataProvider.getList().add(TreeWorkspacePresenter.rootFolder);

                return new DefaultNodeInfo<FileEntity>(dataProvider,
                        new FileCell());
            } else {

                                // Otherwise I know that we are loading some tree child data, and I invoke the AsyncProvider to load it from the server
                provider.setFocusFile(value);

                return new DefaultNodeInfo<FileEntity>(provider,
                        new FileCell());
            }
        }

        public boolean isLeaf(Object value) {

            if(value == null || value instanceof Folder)
                return false;
            return true;
        }

    }

    public class FileDataProvider extends AsyncDataProvider<FileEntity> {

        private FileEntity focusFile;
        private FileService service; 

        @Inject
        public FileDataProvider(FileService service){
            this.service = service;
        }

        public void setFocusFile(FileEntity focusFile){
            this.focusFile = focusFile;
        }

        @Override
        protected void onRangeChanged(HasData<FileEntity> display) {


                service.getChildren(((Folder) focusFile),
                        new Reciever<List<FileEntity>>() {

                            @Override
                            public void onSuccess(List<FileEntity> files) {

                                updateRowData(0, files);

                            }

                            @Override
                            public void onFailure(Throwable error) {

                                Window.alert(error.toString());
                            }

                        });

            }
        }



    /**
     * The cell used to render Files.
     */
    public static class FileCell extends AbstractCell<FileEntity> {

        private FileEntity file;

        public FileEntity getFile() {
            return file;

        }

        @Override
        public void render(Context context, FileEntity file, SafeHtmlBuilder sb) {
            if (file != null) {
                this.file = file;
                sb.appendEscaped(file.getName());
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

小智 2

目前,即使在最新的 gwt 版本中,也不直接支持单个树项刷新。

但有一个解决方法。每个树项都与一个值相关联。使用这个值你可以得到相应的树项。

在您的情况下,我假设您知道要更新/刷新哪个项目,即您知道哪个文件实体已更改。使用此文件实体来搜索相应的树项。获得树项目后,您只需要展开和折叠或折叠和展开其父项目。这使得父项重新渲染其子项。您更改的文件实体是子实体之一。于是就焕然一新。

public void refreshFileEntity(FileEntity fileEntity)
{
       TreeNode fileEntityNode = getFileEntityNode(fileEntity, cellTree.getRootTreeNode() 

       // For expnad and collapse run this for loop

       for ( int i = 0; i < fileEntityNode.getParent().getChildCount(); i++ )
    {
        if ( !fileEntityNode.getParent().isChildLeaf( i ) )
        {
            fileEntityNode.getParent().setChildOpen( i, true );
        }
    }

}

public TreeNode getFileEntityNode(FileEntity fileEntity, TreeNode treeNode)
{
       if(treeNode.getChildren == null)
       {
           return null;
       }
       for(TreeNode node : treeNode.getChildren())
       {
            if(fileEntity.getId().equals( node.getValue.getId() ))
            {
                 return node;
            }
            getEntityNode(fileEntity, node); 
       }
}
Run Code Online (Sandbox Code Playgroud)