【问题标题】:How to use a ListView with an Iterator如何使用带有迭代器的 ListView
【发布时间】:2020-12-22 09:21:51
【问题描述】:

我想为时间线构建一个ListView 的“消息卡”。消息数据来自具有多个过滤功能的 Container 类。我在示例中只展示了一个。

编辑:澄清 我目前使用 ListView.builder() 让这个 ListView 工作,这取决于能够通过索引访问源数据中的元素。

我想更改它,以便元素来自一个可迭代对象,该可迭代对象在用户滚动列表视图时按需生成。

在当前的工作解决方案中,Provider 有一个 findByChildId,它返回一个 List。此列表通常很长,用户可能只想查看最后 100 条左右的消息。

因此,为了不扫描数千条消息以返回数千条消息,我想象使用 findByChildId 会在用户滚动时产生项目。

class MessageData with ChangeNotifier {
  List<MessageRec> _messages;

  // New Iterable to lazily search only for items the user wants to look at
  Iterable<MessageRec> filterByChildId({String childId}) sync* {
    if (childId == null) {
      throw 'insanity check - Cannot search for null Child ID';
    }
    String previous;
    if (_messages != null) {
      for (MessageRec r in _messages) {
        if (r.properties['thread'] == childId) {
          if (previous == null || ymdFromDt(r.timeSent) != previous) {
            yield DateMark.fromDateString(previous); // Special Message inserted 
            previous = ymdFromDt(r.timeSent);
          }
          yield r;
        }
      }
    }
  }

  // And many other supporting methods here.
}

Note: I assume the above works - this is my first forray into Iterables in Dart / flutter.

The above used to be a method that returned a list of MessageRec by iterating over the entire list and returning all matching items.

The ListView.builder could get items from the resulting list because the elements of a List can be accessed by index.

```dart
   ... Timeline Widget ...
 
   @override
   Widget build(BuildContext context) {
      return Consumer<MessageData>(
         builder: (context, messageData, _) {
            return ListView.builder((context, itemIndex) {
    
               // How to access elements from messageData.filterByChildId(childId) here
               MessageRec nextMessage = messageData.filterByChildId(childId)[itemIndex];
               // The above does not work because there is no indexing on Iterables
               
               return MessageCard.fromMessageRec(nextmessage);
               }
            );
         }
      );
    }
... snip rest of Widget methods

或者答案可能在于使用带有 children 的普通 ListView 来自迭代器,但我认为这仍然会最终创建列表中的所有消息。

【问题讨论】:

  • 仔细阅读Iterable官方文档
  • 如果可以请给出答案。我已阅读文档。谢谢。
  • 您没有看到Iterable.toList / Iterable.elementAt 方法?
  • 这只会解决问题。然后我仍然会使用列表。我的问题可能不清楚 - 我试图避免使用列表。我将更新问题以表明这一点。
  • 我正在尝试弄清楚 elementAt 到底是做什么的。从源代码看来,每次调用都会重新开始迭代。这比只使用 toList() 更糟糕!

标签: flutter asynchronous dart iterator


【解决方案1】:

尽管有名称,ListView 并不强制使用 List。您只需要在默认构造函数中使用List,但如果您使用ListView.builder,您可以使用Iterable 来生成值。这是一个例子:

@override
Widget build(BuildContext context) =>
  ListView.builder(
    itemBuilder: (BuildContext _, int i) => 
      MessageCard.fromMessageRec(messageData.filterByChildId(childId).elementAt(i)
  );

至于允许的物品数量,ListView.builder 的文档指出:

此构造函数适用于具有大(或 无限)孩子的数量,因为建造者只被要求 那些实际可见的孩子。 块引用

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-24
    • 1970-01-01
    • 1970-01-01
    • 2013-06-02
    • 2019-05-10
    • 2017-07-27
    • 1970-01-01
    相关资源
    最近更新 更多