Vaadin 14.CallbackDataProvider。当服务缓慢且应答时间较长时,连接到 CallbackDataProvider 的网格会随着所有 UI 卡住。 一些例子:
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.data.provider.CallbackDataProvider;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.router.RouteAlias;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.*;
public class GridWithSortableColumnsView extends VerticalLayout {
public GridWithSortableColumnsView() {
addClassName("dialogwithgrid-view");
setSizeFull();
// prepare Data
List<GridRow> gridRows = new LinkedList<>();
for (int i = 0; i < 10000; i++) {
gridRows.add(new GridRow(i, RandomStringUtils.randomAlphanumeric(10)));
}
CallbackDataProvider<GridRow, Void> dataProvider = new CallbackDataProvider<>(
query -> {
// Slow service answer is here
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Notification.show("Offset=" + query.getOffset() + " Limit=" + query.getLimit());
return gridRows.stream()
.sorted((o1, o2) -> StringUtils.compare(o1.getCol05(), o2.getCol05()))
.skip(query.getOffset())
.limit(query.getLimit());
},
query -> gridRows.size());
Grid<GridRow> grid = new Grid<>();
grid.setPageSize(10);
grid.setSizeFull();
grid.addColumn(GridRow::getId).setHeader("Id");
grid.addColumn(GridRow::getCol05).setHeader("col05");
grid.setDataProvider(dataProvider);
add(grid);
}
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@AllArgsConstructor
@Getter
@Setter
public static class GridRow {
@EqualsAndHashCode.Include
private int id;
private String col05;
}
}
滚动此网格时, session 被锁定,所有 UI 组件都会卡住。 如何才能更快、更异步?我考虑在自己的 DataProvider 扩展 CallbackDataProvider 内部进行缓存,但它会在网格在第一次请求时收到空数据后填充,并且只能在再次刷新 DataProvider 一段时间后使用。这对我来说没有用。在我的实际项目中,获取的数据经常更改,并且项目数量较多,一个网格最多可达 100000 个项目,因此我需要使用请求大小有限的 CallbackDataProvider。
最佳答案
瓦丁 23:
在 Vaadin 23 中现在有一个新功能,它允许您为 DataCommunicator 定义执行器以用于与 Grid 进行异步操作。如果值为空,DataCommunicator 将同步运行,这是默认值。如果定义了执行程序,则执行程序将运行获取回调,并使用 UI#access(..)
更新网格。这需要启用推送。
grid.getDataCommunicator().enablePushUpdates(Executors.newCachedThreadPool());
瓦丁 14:
可以尝试使用缓存来减少查询时间。您可以使用一些通用缓存(例如 ehcache),也可以将缓存集成到数据提供程序中。它是特定于应用程序的,全局或本地缓存更适合您。
如果查询仍然需要那么长时间,那么我会为您的 UI 提出替代方法。不要使用回调数据提供程序,而是将 Grid 与内存数据提供程序一起使用,但不要立即将整个数据加载到数据提供程序。相反,创建一个分页 View 。当用户点击时查询新数据“下一个”/“上一个”等按钮。并在查询完成时使用 UI#access
异步方法更新 UI。
关于callback - Vaadin CallbackDataProvider 如何异步获取数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69942097/