在Objectify / Google App Engine中使用/搜索AsyncDataProvider

时间:2012-06-11 22:45:21

标签: google-app-engine gwt paging objectify dataprovider

我目前有一个使用活动/地点和AsyncDataProvider的应用程序。

现在,每次活动加载时 - 它都会使用请求工厂来检索数据(目前不是很多,但很快就会变得非常大)并将其传递给View以更新DataGrid。在更新之前,它会根据搜索框进行过滤。

现在 - 我已经实现了如下更新DataGrid :(这段代码不是最漂亮的)

private void updateData() {
  final AsyncDataProvider<EquipmentTypeProxy> provider = new AsyncDataProvider<EquipmentTypeProxy>() {

    @Override
    protected void onRangeChanged(HasData<EquipmentTypeProxy> display) {
      int start = display.getVisibleRange().getStart();
      int end = start + display.getVisibleRange().getLength();
      final List<EquipmentTypeProxy> subList = getSubList(start, end);
      end = (end >= subList.size()) ? subList.size() : end;
      if (subList.size() < DATAGRID_PAGE_SIZE) {
        updateRowCount(subList.size(), true);
      } else {
        updateRowCount(data.size(), true);
      }
      updateRowData(start, subList);
    }

    private List<EquipmentTypeProxy> getSubList(int start, int end) {
      final List<EquipmentTypeProxy> filteredEquipment;
      if (searchString == null || searchString.equals("")) {
        if (data.isEmpty() == false && data.size() > (end - start)) {
          filteredEquipment = data.subList(start, end);
        } else {
          filteredEquipment = data;
        }
      } else {
        filteredEquipment = new ArrayList<EquipmentTypeProxy>();
        for (final EquipmentTypeProxy equipmentType : data) {
          if (equipmentType.getName().contains(searchString)) {
            filteredEquipment.add(equipmentType);
          }
        }
      }
      return filteredEquipment;
    }
  };
  provider.addDataDisplay(dataGrid);
} 

最终 - 我想要做的只是首先加载必要的数据(此应用程序中的默认页面大小为25)。

不幸的是,根据我目前的理解,使用Google App Engine时,任何Id都没有订单(一个条目的ID为3,下一个条目的条目为4203)。

我想知道,使用Objectify时从Google App Engine检索数据子集的最佳方法是什么?

我正在考虑使用Offset和限制,但另一个堆栈溢出帖子(http://stackoverflow.com/questions/9726232/achieve-good-paging-using-objectify)基本上说这是低效的。

我发现的最佳信息是以下链接(http://stackoverflow.com/questions/7027202/objectify-paging-with-cursors)。这里的答案是说使用Cursors但也说这是低效的。我也在使用Request Factory,所以我必须将Cursor存储在我的用户Session中(如果这不正确请告诉我。)

目前由于不太可能有大量数据(未来几个月总共可能有200行),我只是将整套设备作为临时黑客退回客户端 - 我知道这是最糟糕的方式要做到这一点,但希望在浪费时间实施另一个黑客解决方案之前获得最佳方式的输入。我现在很担心,因为看起来我读过这篇文章的每一篇文章都让人感觉好像没有一个可靠的方法来做到这一点。

我正在考虑做什么 - 目前我的搜索/页面加载速度很快,因为所有数据都已经在客户端。我在搜索框中使用KeyUpEvent处理程序来过滤数据 - 我认为没有办法通过调用服务器来保持这种速度 - 这个问题是否有任何可接受的解决方案?

非常感谢

1 个答案:

答案 0 :(得分:2)

使用游标。它们和它一样有效 - 游标存储上次查询结束的点并从那里继续。您链接的答案实际上并未讨论游标与偏移的效率。 (有评论说错了)

您可以使用游标限制 - 它不会影响效率。

此外,游标可以通过cursor.toWebSafeString()序列化并通过RPC发送给客户端。这样您就不需要在会话中保存它们。实际上你也可以将它们用作fragment identifier(在GWT用语中也称为历史记录) - 这样就可以将结果集的某个“页面”加入书签。

(Offset是“效率低下”,因为它实际加载并向您收费,对于所有实体,最多为偏移+限制,位仅返回限制实体)

OTOH,如果您在加载页面时已经知道查询参数,那么只需在页面生成时执行查询,而不是通过RPC调用它。此外,如果您有一小组数据(&lt; 1000),您可以预加载页面html的所有实体ID。