【问题标题】:GWT CellTable rebuilding rows unnecessarilyGWT CellTable 不必要地重建行
【发布时间】:2015-09-22 14:31:02
【问题描述】:

我发现了一个有趣的问题,我想知道我是否误用或忽略了某些内容。我有一个可垂直滚动的大 CellTable。我想一次显示所有行而不是传统的分页。所以在我的表格底部有一行,用户可以单击以加载 50 多行。我为该表提供了一个自定义表生成器 (setTableBuilder(new Builder());)。当用户单击“加载更多”时,我查询数据,添加到 ListDataProvider 并调用 table.setVisibleRange(0, dataProvider.getList().size());。

我把日志语句放在了

@Override
public void buildRowImpl(Object rowValue, int absRowIndex) {
}

查看何时构建行的方法。我注意到它会构建 0-dataProvider.getList().size() (所有行),然后它会构建 oldLength-dataProvider.getList().size() (新行)。例如,如果我有 100 行,然后再加载 50 行,它将构建 0-150,然后再构建 100-50。显然,我想要的是它只构建新行。

所以我开始调试,看看为什么每次都重建整个表。我在 com.google.gwt.user.cellview.client.HasDataPresenter 中发现它会在第 1325 行将“redrawRequired”标志设置为 true:

else if (range1 == null && range0 != null && range0.getStart() == pageStart
    && (replaceDiff >= oldRowDataCount || replaceDiff > oldPageSize)) {
  // Redraw if the new data completely overlaps the old data.
  redrawRequired = true;
}

所以我的问题是为什么它认为新数据与旧数据完全重叠?

我是不是用错了东西,有没有更好的方法?当它必须重绘数千行不需要重绘的行时,这会变得相当缓慢。

谢谢, 会

【问题讨论】:

    标签: gwt datagrid celltable gwt-celltable


    【解决方案1】:

    我认为,在这种情况下,CellTable 可以对 setVisibleRange() 方法的调用做出反应的唯一方法是重绘所有行。

    您刚刚通知CellTable,现在它必须显示新范围(0-150 行)而不是最后一个(0-100 行)。没有信息表明第 0-100 行保持不变,无需重绘。

    有趣的是你发现新行被更新(重建)了两次:

    例如,如果我有 100 行,然后再加载 50 行,它将构建 0-150,然后再构建 100-50

    我试图在最小的例子中重现这种行为:

    public class ListDataProviderTest implements EntryPoint {
    
        private static final int ADD_COUNT = 10;
    
        private int nextVal = 0;
    
        public void onModuleLoad() {
            final CellTable<Integer> cellTable = new CellTable<Integer>();
            cellTable.addColumn(new TextColumn<Integer>() {
                @Override
                public String getValue(Integer object) {
                    return object.toString();
                }});
    
            final ListDataProvider<Integer> listDataProvider = new ListDataProvider<Integer>();
    
            listDataProvider.addDataDisplay(cellTable);
    
            RootPanel.get().add(cellTable);
            RootPanel.get().add(new Button("Add more...", new ClickHandler() {
                @Override
                public void onClick(ClickEvent event) {
                    List<Integer> list = listDataProvider.getList();
                    for(int i = 0; i < ADD_COUNT; i++)
                        list.add(nextVal++);
                    cellTable.setVisibleRange(0, list.size());
                }
            }));
        }
    }
    

    但我将所有行更新一次。

    您能否确认此示例重现了该问题或更准确的示例?

    【讨论】:

    • 所以我意识到新 50 行中的部分信息是异步加载的,所以当它进来时,我让它重绘新行,这就是为什么它会加载最后 50 行。我猜我希望找到的是一种强制表格增加大小并只构建新行的方法。
    【解决方案2】:

    AFAIK 一个 CellTable 总是重绘所有单元格。 这就是 CellTable 中的渲染器的工作方式。虽然它总是重绘所有单元格,但在大多数情况下,它仍然比使用 FlexTable 并且只更新几个单元格要快。

    【讨论】:

    • 如果您查看 com.google.gwt.user.cellview.client.HasDataPresenter,您将在私有 boolean resolvePendingState(JsArrayInteger modifiedRows) 方法中看到它计算哪些行被修改以及什么是需要重绘
    • 请务必展示您的发现和意见(“据我所知”),并不能帮助我弄清楚这一点
    猜你喜欢
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多