Vaadin Grid启用Push后内容未按预期异步加载问题求助
Vaadin Grid 异步加载内容未逐个刷新的问题
我在使用开启Push功能的Vaadin Grid,预期实现:实体已有的数据立即加载,异步方法获取的数据通过回调逐个更新到网格中。但目前网格框架能立即显示,所有内容却要等待较长时间后一次性加载完成。
原代码示例
Grid 初始化代码
private void setupGrid() { // String grid for illustration Grid<String> grid = new Grid<>(); grid.addComponentColumn(this::getIconColumn).setHeader("Name"); // other entity items would be displayed here // grid.addComponentColumn(this::getMainColumn).setHeader("Other"); grid.setItems("2800-player-who-returned-10000-years-later", "2633-duke-pendragon", "8713-dungeon-reset"); // this allows the outer grid structure to be displayed while not blocking UI // but content is still loaded "synchronously" - all at once, not one by one grid.getDataCommunicator().enablePushUpdates(Executors.newCachedThreadPool()); add(grid); }
组件列异步加载方法
private Image getIconColumn(String entityName) { Image image = new Image("", ""); image.setHeight("150px"); image.setWidth("100px"); UI ui = UI.getCurrent(); asyncLoadIcon(entityName) .addCallback( result -> ui.access(() -> image.setSrc(result)), err -> ui.access(() -> Notification.show("Failed to parse icon for " + entityName)) ); return image; }
异步加载工具方法
@Async public ListenableFuture<String> asyncLoadIcon(String entityName) { try { // some real code Thread.sleep(3000); return AsyncResult.forValue(entityname); } catch (IOException | InterruptedException e) { log.error(e); } return AsyncResult.forExecutionException(new RuntimeException("Error")); }
问题原因
enablePushUpdates仅作用于Grid数据通信器的后台数据处理,对组件列内部单个组件的异步更新无直接效果。- Vaadin默认会合并
UI.access中的更新操作,延迟推送,导致所有异步任务完成后一次性刷新界面。 - 异步方法存在拼写错误:
entityname应改为entityName,会导致返回无效结果。
解决方案
1. 确保Vaadin Push配置正确
在Spring Boot项目的application.properties中添加:
vaadin.push.enabled=true vaadin.push.mode=automatic
2. 修改组件列更新逻辑,手动触发推送
在UI.access中更新组件后,调用ui.push()强制立即推送更新,避免批量合并:
private Image getIconColumn(String entityName) { Image image = new Image("", ""); image.setHeight("150px"); image.setWidth("100px"); UI ui = UI.getCurrent(); asyncLoadIcon(entityName) .addCallback( result -> ui.access(() -> { image.setSrc(result); // 手动触发推送,确保单个组件更新立即生效 ui.push(); }), err -> ui.access(() -> { Notification.show("Failed to parse icon for " + entityName); ui.push(); }) ); return image; }
3. 修正异步方法的拼写错误
@Async public ListenableFuture<String> asyncLoadIcon(String entityName) { try { // 实际业务代码 Thread.sleep(3000); return AsyncResult.forValue(entityName); // 修正变量名拼写 } catch (IOException | InterruptedException e) { log.error("加载图标失败", e); } return AsyncResult.forExecutionException(new RuntimeException("Error")); }
4. 优化线程池配置
避免使用无界的CachedThreadPool,改用有界线程池控制并发数,防止资源耗尽:
grid.getDataCommunicator().enablePushUpdates(Executors.newFixedThreadPool(5));
内容的提问来源于stack exchange,提问作者Michael Kročka
相关产品推荐
相关产品推荐

