Flutter FlatterFireStore—检索只属于某一组ID的文档快照,并在屏幕上显示该数据

Flutter FlatterFireStore—检索只属于某一组ID的文档快照,并在屏幕上显示该数据,flutter,google-cloud-firestore,flutter-futurebuilder,Flutter,Google Cloud Firestore,Flutter Futurebuilder,我正在传递Firestore文档ID的构造函数列表,我只想在“LinksData”集合中检索和显示属于这些ID的数据 因此,基本上我希望检索属于id的所有文档的文档快照,这些文档位于我的另一个列表中(我正在将其传递给构造函数) 我可以想出两种方法: 使用StreamBuilder,但据我所知,使用它,我将获得集合中的所有文档快照,或者只获得一个快照 使用Future Builder,我创建了以下函数,但当我使用它时,它显示以下错误 我该怎么做?我不想使用stream builder检索所有文档,

我正在传递Firestore文档ID的构造函数列表,我只想在“LinksData”集合中检索和显示属于这些ID的数据

因此,基本上我希望检索属于id的所有文档的文档快照,这些文档位于我的另一个列表中(我正在将其传递给构造函数)

我可以想出两种方法:

  • 使用StreamBuilder,但据我所知,使用它,我将获得集合中的所有文档快照,或者只获得一个快照
  • 使用Future Builder,我创建了以下函数,但当我使用它时,它显示以下错误
  • 我该怎么做?我不想使用stream builder检索所有文档,因为这会影响我的日常阅读。

    下面是我如何尝试使用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];
                            });
                      }
                    },
                  )
    
    FutureBuilder(
    未来:generateList(widget.linksDataIds),
    生成器:(上下文,快照){
    if(snapshot.hasError){
    返回中心(子:Text('Oops!发生了一些错误!'));
    }否则{
    如果(!snapshot.hasData){
    返回中心(子项:CircularProgressIndicator());
    }
    返回GridView.builder(
    gridDelegate:SliverGridDelegateWithMaxCrossAxisExtent(
    maxCrossAxisExtent:220,
    主轴间距:12.0,
    ),
    itemCount:snapshot.data!.length,
    itemBuilder:(上下文,索引){
    返回snapshot.data![index];
    });
    }
    },
    )
    
    这是我的未来

      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;
      }
    
    Future generateList(列表链接SDataId)异步{
    FirebaseFirestore=FirebaseFirestore.instance;
    列表卡片=[];
    forEach((linkDataId)异步{
    打印(linkDataId);
    等待火库
    .collection('LinksData')
    .doc(linkDataId)
    .get()
    。然后((值)=>{
    列表卡。添加(链接卡)(
    link:value.get('link'),
    linkTitle:value.get('title'),
    linkImage:value.get('image'),
    relatedCategories:value.get('categories'),
    平台:value.get('platform'),
    ))
    });
    });
    返回列表卡;
    }
    

    下面是我的数据库结构的图像:

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

    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 generateList(列表链接SDataId)异步{
    FirebaseFirestore=FirebaseFirestore.instance;
    列表卡片=[];
    
    对于(inti=0;i,这应该可以让您非常接近。这是一个简化的示例,我可以使用字符串列表重现它

    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;
      }
    

    然后您可以从那里修改以完全填充您的
    链接卡

    谢谢您的回复,但我通过稍微修改一下数据库找到了解决方案。 在“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'));
                            });
                      }
                    },
                  )
    
    StreamBuilder(
    流:FirebaseFirestore.instance
    .collection('LinksData')
    .where('categories',arrayContains:widget.categoryName)
    .snapshots(),
    生成器:(上下文,快照){
    if(snapshot.hasError){
    返回中心(子项:文本('${snapshot.error}');
    }否则{
    如果(!snapshot.hasData){
    返回中心(子项:CircularProgressIndicator());
    }
    返回GridView.builder(
    gridDelegate:SliverGridDelegateWithMaxCrossAxisExtent(
    maxCrossAxisExtent:220,
    主轴间距:12.0,
    ),
    itemCount:snapshot.data!.docs.length,
    itemBuilder:(上下文,索引){
    返回链接卡(
    linkImage:snapshot.data!.docs[index].get('image'),
    linkTitle:snapshot.data!.docs[index].get('name'),
    链接:snapshot.data!.docs[index].get('link'),
    relatedCategories:snapshot.data!.docs[index].get('categories'),
    平台:snapshot.data!.docs[index].get('platform');
    });
    }
    },
    )
    
    这样,控件进入snapshot.hasError,并进一步打印firestoreResult.data()[“link”],它仍然给出null.,即使它在数据库中。错误是因为此函数不知道什么是
    linkDataId
    。在原始问题中,它来自
    forEach
    循环,但在这个循环中,常规for循环
    linkDataId
    根本不存在。
    Expanded(
       child: ListView.builder(
          itemCount: snapshot.data!.length,
          itemBuilder: (context, index) =>
             Text(snapshot.data![index])),
       );
    
    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'));
                            });
                      }
                    },
                  )