【问题标题】:Flutter Streambuilder map to List objectFlutter Streambuilder 映射到 List 对象
【发布时间】:2020-04-21 18:17:02
【问题描述】:

我需要在 Flutter 中显示一个列表视图,其中包含来自 firestore 的数据。然后我希望用户能够通过在应用栏的文本字段中键入他的查询来过滤列表视图。这是我为列表视图提出的代码:

_buildAllAds() {

  return StreamBuilder(
    stream: Firestore.instance.collection("Classificados")
    .orderBy('title').snapshots().map((snap) async {
      allAds.clear();
      snap.documents.forEach((d) {
        allAds.add(ClassificadoData(d.documentID,
          d.data["title"], d.data["description"], d.data["price"], d.data["images"] ));
       
      });

    }),
    builder: (context, snapshot) {

      // if (!snapshot.hasData) {
      //  return Center(child: CircularProgressIndicator());
      //  }
      //else{
      //}
      if (snapshot.hasError) {
        print("err:${snapshot.error}");
      }
      
      return ListView.builder(
        itemCount: allAds.length,
        itemBuilder: (context, index) {
          ClassificadoData ad = allAds[index];
          return ClassificadosTile(ad);

        });
    });

}

我将流数据保存在 List allAds of type ClassificadoData (数据项是广告)中的原因是我可以将其复制到另一个 List filteredAds用户可以进行过滤。我需要 allAds 流的原因是我希望用户能够实时看到添加/更新。 所以这段代码“有效”,但感觉有点尴尬,我也不能对构建器做任何事情,因为 snaphot 一直保持为空(例如,在初始数据获取期间无法显示加载器)。 想知道是否有更可靠的方法来做我想做的事情,以及是否有可能将快照的引用传递给构建器。

【问题讨论】:

  • 我不确定我是否理解您的问题。当您说“我想要并且是否有可能将快照的引用传递给构建器。”时,您能否详细说明您的意思?当您说代码有效但快照仍然为空时,这也有点令人困惑。
  • 我建议您使用已经实施的颤振搜索,而不是重新发明轮子。检查这个问题stackoverflow.com/questions/58908968/…
  • @JoãoSoares snapshot = null 但所有广告都同样填充了 LisView.builder。这就是我所说的“尴尬”。
  • @Salma.With Flutter ShowSearch 的问题仍然是在流中显示初始数据(应该对后端的变化做出反应)并将流数据转换为可以搜索的列表(否则我们需要每次用户在查询中键入时,都从数据库中获取和过滤数据)。

标签: flutter google-cloud-firestore


【解决方案1】:

您似乎混合了使用流和流相关小部件的两种不同概念。理想情况下,您可以使用 StreamBuilder 并直接在 Widget 上使用从流中获取的数据,或者侦听数据并更新一个变量,然后用于填充您的 ListView。我已经从您的代码中构建了后者作为示例:

@override
initState(){
  _listenToData();
  super.initState();
}

_listenToData(){
  Firestore.instance.collection("Classificados")
    .orderBy('title').snapshots().listen((snap){
    allAds.clear();
    setState(() {
      snap.documents.forEach((d) {
        allAds.add(ClassificadoData(d.documentID,
          d.data["title"], d.data["description"], d.data["price"], d.data["images"] ));
      });
    });
  });
}

_buildAllAds() {
  return ListView.builder(
    itemCount: allAds.length,
    itemBuilder: (context, index) {
      ClassificadoData ad = allAds[index];
      return ClassificadosTile(ad);
    }
  );
}

【讨论】:

  • 感谢您的回答。这正是我的第一个方法。问题是当后端更新时 listvew 不会实时更新,因为监听器仅在 initstate 中被调用。像这样,如果数据库被更新,监听器肯定会触发,但是我如何将更新传播到构建?
  • 一旦您开始收听 Firestore 集合,您无需在每次重建时都重新收听。您只需要在 initState 上执行一次。如果您正在收听的集合直接发生更改,则监听将触发。
猜你喜欢
  • 2021-11-16
  • 1970-01-01
  • 2020-11-29
  • 1970-01-01
  • 2017-03-03
  • 1970-01-01
  • 2022-07-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多