Vaadin:如何从其他线程实时更新Grid组件数据?
解决Vaadin Grid后台线程更新不即时显示的问题
问题分析
你的代码存在两个核心问题导致数据无法自动刷新:
- 全局存储
UI.getCurrent()实例有风险,若用户在异步操作完成前切换页面/刷新,该实例可能已失效。 - 未启用Vaadin的Push推送机制,后台线程更新UI后无法主动同步到客户端,只能等用户交互触发请求才会更新。
修复方案
1. 启用Push功能
Push是Vaadin实现后台UI更新主动推送的核心机制,配置方式如下:
- 若为Spring Boot项目,在
application.properties中添加:
vaadin.push.enabled=true vaadin.push.mode=automatic
- 或直接在你的UI类上添加注解:
@Push public class YourMainUI extends UI { // 你的UI逻辑 }
2. 修正后台线程更新代码
不要全局缓存UI实例,改用Vaadin官方推荐的安全更新方式,同时移除不必要的页面重载:
taskSlaService.getFilterAsync(pointId, dictValueIds) .thenAcceptAsync(entities -> { log.info("entities {}", entities); if (entities.isEmpty()) { log.info("entities is empty =====> {}", entities); } // 通过VaadinSession执行UI更新,自动处理线程安全 VaadinSession.getCurrent().access(() -> { UI ui = UI.getCurrent(); if (ui != null) { log.info("========> UI isn't null"); grid.setItems(entities); // setItems已完成数据替换,无需额外调用refreshAll log.info("entities in UI.access =====> {}", entities); log.info(Thread.currentThread().getName()); // 移除页面重载,这会覆盖异步更新的效果 // ui.getPage().reload(); } }); });
关键注意事项
- 禁止全局存储
UI或VaadinSession实例,它们与用户会话绑定,随时可能失效。 - 所有UI更新操作必须放在
VaadinSession.access()或UI.access()中执行,这会自动处理锁机制和线程安全。 - 启用Push后,后台线程的UI变更会直接推送到客户端,无需用户交互触发。
内容的提问来源于stack exchange,提问作者Алексей Шерстобитов
相关产品推荐
相关产品推荐

