Flutter Firestore - 检索仅属于一组特定 ID 的文档快照并在屏幕上显示该数据

Flutter Firestore - To retrieve document snapshots belonging to only a certain set of ids and show that data on screen

我正在传递我的 Firestore 文档 ID 的构造函数列表,我只想在我的 'LinksData' collection.

中检索和显示属于这些 ID 的数据

所以基本上我想检索属于我的另一个列表中的所有文档的文档快照(我正在将其传递给构造函数)。

我想到了两种方法:

  1. 使用 StreamBuilder,但据我所知,有了这个我将在我的 collection 中获取所有文档快照,或者只获取一个。
  2. 使用 Future Builder,我做了以下功能,但是当我使用它时,它显示以下错误
[ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: Bad state: field does not exist within the DocumentSnapshotPlatform

我该怎么做?我不想使用流生成器检索所有文档,因为那会影响我的日常阅读。

这是我尝试使用 FutureBuilder 的代码。

FutureBuilder<List<LinkCards>>(
                future: generateList(widget.linksDataIds),
                builder: (context, snapshot) {
                  if (snapshot.hasError) {
                    return Center(child: Text('Oops! Some Error Occurred!'));
                  } else {
                    if (!snapshot.hasData) {
                      return Center(child: CircularProgressIndicator());
                    }
                    return GridView.builder(
                        gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
                          maxCrossAxisExtent: 220,
                          mainAxisSpacing: 12.0,
                        ),
                        itemCount: snapshot.data!.length,
                        itemBuilder: (context, index) {
                          return snapshot.data![index];
                        });
                  }
                },
              )

这是我的 Future 函数

  Future<List<LinkCards>> generateList(List<dynamic> listLinksDataId) async {
    FirebaseFirestore fireStore = FirebaseFirestore.instance;
    List<LinkCards> listCards = [];

    listLinksDataId.forEach((linkDataId) async {
      print(linkDataId);

      await fireStore
          .collection('LinksData')
          .doc(linkDataId)
          .get()
          .then((value) => {
                listCards.add(LinkCards(
                  link: value.get('link'),
                  linkTitle: value.get('title'),
                  linkImage: value.get('image'),
                  relatedCategories: value.get('categories'),
                  platform: value.get('platform'),
                ))
              });
    });
    return listCards;
  }

这是我的数据库结构的图像:enter image description here

这就是您的函数的理想外观。 试一试,希望它能奏效。

Future<List<LinkCards>> generateList(List<dynamic> listLinksDataId) async {
    FirebaseFirestore fireStore = FirebaseFirestore.instance;
    List<LinkCards> listCards = [];
    for(int i=0; i<listLinksDataId.length;i++){

       final firestoreResult = await fireStore
          .collection('LinksData')
          .doc(linkDataId)
          .get();
       listCards.add(
        link: firestoreResult.data()["link"],
        linkTitle: firestoreResult.data()["title"],
        linkImage: firestoreResult.data()["image"],
        relatedCategories: firestoreResult.data()["categories"],
        platform: firestoreResult.data()["platform"],
       );

    }
    return listCards;
  }

这是我通常采用的方法,希望对您也有用。

这应该让你很接近。这是一个我可以重现的简化示例,它只使用一个字符串列表。

Future<List<String>> generateList(List<String> listLinksDataId) async {
    List<String> listCards = [];
    final collection = FirebaseFirestore.instance.collection('LinksData');
    for (String docId in listLinksDataId) {
      final snapshot = await collection.doc(docId).get(); 

     // snapshot is the document snapshot whose id 
     // matches the index in the list you're passing in

      final linksData = snapshot['linksData']; // list of ids in linksData field

      for (var i = 0; i < linksData.length; i++) { // looping through list
        final field = linksData[i];
        listCards.add(field);
      }
    }
    return listCards;
  }

这将至少 return linksData 字段中的所有 ID 仅在与您传入的列表索引匹配的文档中。

您应该能够设置一个快速测试页面和一个 FutureBuilder<ListString>> 并将此方法作为 Future 传递。

Return 一个 ListView 只显示文本小部件,您会看到您想要的所有 ID。

Expanded(
   child: ListView.builder(
      itemCount: snapshot.data!.length,
      itemBuilder: (context, index) =>
         Text(snapshot.data![index])),
   );

然后您可以从那里修改以完全填充您的 LinkCard

感谢您的回复,但我通过稍微修改我的数据库找到了解决方案。 在 'LinksData' 集合中,我放置了一个包含所有类别的字段(类型数组)。然后我像这样使用 StreamBuilder :

StreamBuilder<QuerySnapshot>(
                stream: FirebaseFirestore.instance
                    .collection('LinksData')
                    .where('categories', arrayContains: widget.categoryName)
                    .snapshots(),

                builder: (context, snapshot) {
                  if (snapshot.hasError) {
                    return Center(child: Text('${snapshot.error}'));
                  } else {
                    if (!snapshot.hasData) {
                      return Center(child: CircularProgressIndicator());
                    }
                    return GridView.builder(
                        gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
                          maxCrossAxisExtent: 220,
                          mainAxisSpacing: 12.0,
                        ),
                        itemCount: snapshot.data!.docs.length,
                        itemBuilder: (context, index) {
                          return LinkCards(
                              linkImage: snapshot.data!.docs[index].get('image'),
                              linkTitle: snapshot.data!.docs[index].get('name'),
                              link: snapshot.data!.docs[index].get('link'),
                              relatedCategories: snapshot.data!.docs[index].get('categories'),
                              platform: snapshot.data!.docs[index].get('platform'));
                        });
                  }
                },
              )