Vaadin Dataprovider:如何避免“自动获取"? [英] Vaadin Dataprovider: how to avoid "auto-fetch"?

查看:51
本文介绍了Vaadin Dataprovider:如何避免“自动获取"?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

用例 1 的回答如下,用例 2 已移至单独的问题 (Vaadin Flow:返回视图,视图不应从后端重新加载数据)

Use Case 1 is answered below, Use Case 2 has been moved to a separate question (Vaadin Flow: Returning to a view, the view should not reload data from the backend)

我想使用由惰性 DataProvider 支持的 Vaadin Flow (v14 LTS/v19) 网格组件,该组件在显示网格时不会自动从后端获取数据.

I'd like to use a Vaadin Flow (v14 LTS/v19) grid component backed by a lazy DataProvider which does not automatically fetch data from the backend when the grid is shown.

至少有两个用例:

  • 除非用户提供过滤参数,否则显示网格数据没有意义
  • 返回到 @PreserveOnRefresh 标记视图不应将显示的数据替换为当前数据.(在更新中进一步阐述)
  • showing grid data does not make sense unless the user provided filter parameters
  • returning to a @PreserveOnRefresh tagged view should not replace the shown data with current data. (further elaborated in update)

作为 Vaadin 14+ 的新手,我不知道如何实现这一点.每次显示我的 GridView 时,都会查询 DataProvider 的 count 和 fetch 回调.调用源自网格的 DataCommunicator.

Being pretty new to Vaadin 14+, I could not figure out how to achieve this. Every time my GridView is displayed, the count and fetch callbacks of DataProvider are queried. The call originates from the DataCommunicator of the grid.

那么对于用例 1:如何阻止 DataProvider 获取没有意义的数据?对于用例 2:如何防止在第二次向 UI 中添加网格时覆盖网格状态?

So for Use Case 1: How to stop the DataProvider from fetching data as long as it does not make sense? And for Use Case 2: How to prevent overwriting the grid state when adding a grid to the UI for the second time?

非常感谢!

StackTrace 到我的提取回调(Vaadin Flow 14):

StackTrace to my fetch callback (Vaadin Flow 14):

        at org.vaadin.example.GridView.fetch(GridView.java:46)
        at org.vaadin.example.GridView.lambda$new$c4b2c115$1(GridView.java:23)
        at com.vaadin.flow.data.provider.CallbackDataProvider.fetchFromBackEnd(CallbackDataProvider.java:137)
        at com.vaadin.flow.data.provider.AbstractBackEndDataProvider.fetch(AbstractBackEndDataProvider.java:61)
        at com.vaadin.flow.data.provider.DataCommunicator.fetchFromProvider(DataCommunicator.java:362)
        at com.vaadin.flow.data.provider.DataCommunicator.activate(DataCommunicator.java:647)
        at com.vaadin.flow.data.provider.DataCommunicator.collectKeysToFlush(DataCommunicator.java:589)
        at com.vaadin.flow.data.provider.DataCommunicator.flush(DataCommunicator.java:461)
        at com.vaadin.flow.data.provider.DataCommunicator.lambda$requestFlush$2f364bb9$1(DataCommunicator.java:425)
        at com.vaadin.flow.internal.StateTree.lambda$runExecutionsBeforeClientResponse$2(StateTree.java:390)
        at [java.util.stream] omitted
        at com.vaadin.flow.internal.StateTree.runExecutionsBeforeClientResponse(StateTree.java:387)
        at com.vaadin.flow.server.communication.UidlWriter.encodeChanges(UidlWriter.java:411)
        at com.vaadin.flow.server.communication.UidlWriter.createUidl(UidlWriter.java:187)
        at com.vaadin.flow.server.communication.UidlRequestHandler.writeUidl(UidlRequestHandler.java:122)
        at com.vaadin.flow.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:91)
        at com.vaadin.flow.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40)
        at com.vaadin.flow.server.VaadinService.handleRequest(VaadinService.java:1547)
        at com.vaadin.flow.server.VaadinServlet.service(VaadinServlet.java:247)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)


更新20210430这是我的 GridView 的代码,它也伪造了后端 DataProvider:


update 20210430 Here's the code of my GridView which also fakes the backend DataProvider:

@Route(value = "grid", layout = MainView.class)
public class GridView extends VerticalLayout {
    public GridView() {
        final Grid<Person> g = new Grid(Person.class);
        g.setColumns("name");
        g.setDataProvider(DataProvider.fromCallbacks(q -> fetch(q), q -> count(q)));
        add(g);
        // filter omitted
        final Button refresh = new Button("refresh");
        refresh.addClickListener(e -> {
            System.out.println("refresh clicked");
            g.getDataProvider().refreshAll();
        });
        add(refresh);

        add(new TextField("State check"));
    }

    // fake DataProvider
    private int count(Query<Person, Void> q) { return 3; }

    private Stream<Person> fetch(Query<Person, Void> q) {
        q.getLimit(); //vaadin checks these have been called
        q.getOffset(); //vaadin checks these have been called
        System.out.println("fetching again");
        new Exception().printStackTrace(); //figure out who called
        return Arrays.asList(new Person("1"), new Person("2"), new Person("3")).stream();
    }
}

我的MainView用于在GridViewEmptyView

@PreserveOnRefresh
public class MainView extends AppLayout {

    private Component emptyBView;
    private Component gridBView;

    public MainView() {
        final Button emptyB = new Button("Btn empty");
        emptyB.addClickListener(e -> {
            if (emptyBView == null) { emptyBView = new EmptyView();}
            setContent(emptyBView);
        });
        addToNavbar(emptyB);

        final Button gridB = new Button("Btn grid");
        gridB.addClickListener(e -> {
            if (gridBView == null) gridBView = new GridView();
            setContent(gridBView);
        });
        addToNavbar(gridB);
    }
}

MainView 是一个 AppLayout 用于将 AppLayout 的内容从 GridView 切换到 EmptyView 并返回.

MainView is an AppLayout used to switch the contents of the AppLayout from GridView to EmptyView and back.

用例 2 是:当返回到 GridView 时,GridView 应该与之前的状态完全相同(这适用于 TextField).

Use Case 2 is: When returning to GridView, the GridView should be exactly same state as before (which works fine with the TextField).

  1. 打开 GridView ->网格不应填充数据
  2. 输入过滤器参数(代码中未显示)
  3. 点击刷新"填充网格
  4. 输入蜘蛛侠"在 TextField 中stateCheck"
  5. 切换到EmptyView
  6. 在实际应用中:在 EmptyView 和其他可能的视图中做一些事情
  7. 返回GridView ->网格应该不重新加载数据,它应该保持原样 - 就像 TextField 仍然显示蜘蛛侠"一样,网格应该显示与以前相同的数据无需重新加载.
  1. open GridView -> grid should not be filled with data
  2. enter filter params (not shown in code)
  3. click "refresh" to populate the grid
  4. enter "Spiderman" in TextField "stateCheck"
  5. switch to EmptyView
  6. in the real app: do something in EmptyView and potentially other views
  7. return to GridView -> the grid should not reload the data, it should just stay as it was - just like the TextField still displays "Spiderman", the grid should display the same data as before without reloading it.

推荐答案

对于案例 1:在回调中检查是否有过滤器参数,如果没有则返回一个空集.使用新的 V17+ API,它看起来像这样:

For Case 1: In the callback check if you have filter parameters, return an empty set if not. Using the new V17+ API it would look like this:


grid.setItems(query -> {
    if(filterParameters.isEmpty()) {
      // Return an empty stream
    } else {
      // Fetch from backend
    }
});

您可以在此处的文档中阅读更多内容:https://vaadin.com/docs/latest/flow/binding-data/data-provider (V19) 或 https://vaadin.com/docs/v14/flow/binding-data/tutorial-flow-data-provider (V14)

You can read more in the docs here: https://vaadin.com/docs/latest/flow/binding-data/data-provider (V19) or https://vaadin.com/docs/v14/flow/binding-data/tutorial-flow-data-provider (V14)

我需要更多关于您目前正在做什么的信息来帮助解决案例 2.您如何构建视图,您的代码是什么样的?带有Caused by"的完整堆栈跟踪也会有所帮助.

I would need more info on what you're currently doing to help out with Case 2. How are you constructing the view, what does your code look like? A full stack trace with the "Caused by" would also help.

这篇关于Vaadin Dataprovider:如何避免“自动获取"?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆