Vaadin Flow:返回视图,视图不应从后端重新加载数据

Vaadin Flow: Returning to a view, the view should not reload data from the backend

拆分出来。

给定一个带有 MainView extends AppLayoutGridViewEmptyView
的 Vaadin Flow 19 应用,并且 @PreserveOnRefresh 注释用于 MainView.

当return转到GridView时,GridView应该和之前的状态完全一样:

  1. 第一次使用 MainView 中的按钮打开 GridView -> Grid 使用 DataProvider 从后端获取数据
  2. TextField 中输入“蜘蛛侠”,标题为“stateCheck”
  3. 使用 MainView
  4. 中的按钮切换到 EmptyView
  5. 在真实应用中:在 EmptyView 和可能的其他视图中做一些事情
  6. return 到 GridView 第二次使用 MainView 中的按钮

然后 (1) 标题为“stateCheck”的 TextField 应显示值“Spiderman”
并且 (2) 网格仍应显示与之前相同的数据;它应该不从后端重新加载数据

观察到的行为: (1) 可以,但 (2) 不行:网格总是调用 fetch 方法从后端获取数据。

如何实现所需的行为?


这是我的 GridView 的代码,它也伪造了后端 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);

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

这其实是有意为之的行为。当组件分离并在附加时重新连接时,需要删除服务器端数据提供者侦听器。原因是否则会有监听器积累并产生内存泄漏。如果您认为您的用户会经常使用刷新页面,您应该考虑向您的应用程序添加缓存以优化性能。

现在,人们可以考虑在 Grid 中以及在 Vaadin 框架中通过 API 对以前加载的数据行为进行这种缓存的想法,因为它可能是可取的,也可能不是可取的。它是特定于应用程序的。

如果刷新的用例确实是为了获取活动数据库的新鲜数据,那么实际上希望在刷新页面时加载数据。

如果希望避免对数据库的额外轰炸,因为已知数据是静态的,则需要缓存。