【问题标题】:How to Vaadin CallbackDataProvider make an asyncronous fetch data?Vaadin CallbackDataProvider 如何进行异步获取数据?
【发布时间】:2021-12-24 18:05:03
【问题描述】:

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;
    }

}

在滚动此 Grid 时会话被锁定并且所有 UI 组件都冻结。 它如何更快和更异步?我考虑在自己的 DataProvider 中缓存扩展 CallbackDataProvider,但它会在 Grid 在第一次请求时收到空数据后填充,并且可能仅在一段时间后再次刷新 DataProvider 后使用。这对我没用。在我的实际项目中,获取的数据经常变化并且有很多项目,一个网格最多 100000 个项目,所以我需要使用具有有限请求大小的 CallbackDataProvider。

【问题讨论】:

  • 问题是:为什么你的服务很慢?
  • 这是一个数据库查询。有时它很慢,没有可能加快它。数据库是外部项目。
  • 也许我会尝试在自己的 DataProvider 中注入一些异步回调。但是有些情况下,首先 Grid 数据请求它接收带有空实体的 Stream,并且在将正确的数据缓存到缓存后,我将手动调用相同偏移量的刷新并限制缓存中的数据。将发生两次刷新。

标签: callback vaadin-flow dataprovider vaadin-grid vaadin14


【解决方案1】:

可以尝试使用缓存来减少查询时间。您可以使用一些通用缓存,例如 ehcache,也可以将缓存集成到您的数据提供程序中。它是特定于应用程序的,哪个更适合您,全局或本地缓存。

如果查询仍然需要很长时间,那么我会为您的 UI 提出替代方法。不使用回调数据提供程序,而是将 Grid 与内存数据提供程序一起使用,但不要一次将整个数据加载到数据提供程序。而是创建一个分页视图。当用户点击时查询新数据,例如“下一个”/“上一个”等按钮。并在查询完成时使用 UI#access 异步方法更新 UI。

【讨论】:

  • 分页对我们的客户没有用处。他们需要通过排序、过滤和动态更新数据来获取大型网格中的信息。我认为只有可能我们再添加一个 hackish 层作为缓存。我不知道它会有多好,我已经看到了一些问题。顺便说一句 - Vaadin 之前没有想过这个问题吗?这是一个非常烦人的问题。如果可以的话,请解决它。
  • 如果我理解正确,Grid 向 DataCommunicator 询问数据,它从 DataProvider 询问数据。 DataCommunicator 在阻塞模式下等待 DataProvider。为什么不分两步呢?首先是从 DataProvider 获取数据,其次是数据回调准备好刷新 UI?它将是非阻塞架构。
  • 我检查了当前实现的代码,并为运行良好的非阻塞版本制作了本地 mod。我认为这在技术上是可行的,是的。它还为极端情况错误打开了很多可能性,所以我认为当前的选择是有利于简单性和可维护性的。
  • 这里是要点,注意这不是简单的扩展,所以我只是尝试我的猴子补丁gist.github.com/TatuLund/a97e01702705d2a53a67c114e514d8cd
  • 我自然无法针对所有可能的回归测试它。这里有功能请求票,请随时评论并点赞github.com/vaadin/flow-components/issues/1066
【解决方案2】:

您可以使用专门用于搜索/过滤的附加数据库/搜索引擎,它可以非常快速地为您的网格提供数据。 Elasticsearch 是该用例的不错选择。

搜索引擎将仅适用于您的网格。对于所有其他用例(输入表单、处理等),您可以进一步使用当前数据库。

当然你必须实现一个更新机制。每当您当前数据库中的数据发生变化时,您都必须通知 Elasticsearch 系统并更新那里的数据。

【讨论】:

  • 谢谢,我试试看。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-20
  • 1970-01-01
  • 1970-01-01
  • 2012-02-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多