如何使用 Flutter 从 Firebase 中的两个集合中获取数据

Posted

技术标签:

【中文标题】如何使用 Flutter 从 Firebase 中的两个集合中获取数据【英文标题】:How to get data from two collections in firebase using Flutter 【发布时间】:2020-09-08 03:21:40 【问题描述】:

这是我的问题:

我有一个ListPost StatefulWidget,我想在其中显示一个小部件列表,其中包含用户的帐户图像、用户的姓名和用户的帖子图像(类似于 Facebook 提要),但是,我已经明白了我需要从 Firebase 中的两个不同集合中获取该数据(请参阅下面的我的 firebase 集合图片)。

好消息是我只能从一个集合 (userFeed) 中获取该数据,并将该数据显示在我的 ListPost 文件中的不同小部件中,但是,我不知道如何从中获取数据Firebase 中的另一个集合,使用相同的 streamBuilder 并在我的 ListPost 屏幕中显示我想在其他小部件中显示的所有数据。

所以,我的具体问题是: 如何使我的ListPost 屏幕使用流构建器或其他类型的实现来填充来自 Firebase 中 2 个不同集合的数据?

这是 Firebase 图片

这是ListPost屏幕的完整代码

import 'package:cached_network_image/cached_network_image.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'models/post_model.dart';

final _stream = Firestore.instance.collection('userFeed').snapshots();

class ListPosts extends StatefulWidget 

  @override
  _ListPostsState createState() => _ListPostsState();


class _ListPostsState extends State<ListPosts> 


  @override
  Widget build(BuildContext context) 
    return Scaffold(
      body: Container(
        //this is the Streambuilder to get the data however it only lets me to get one collection
        child: StreamBuilder(
          stream: _stream,
          builder: (context, snapshot) 
            if (!snapshot.hasData) return const Text('Loading...');
            return ListView.builder(
              itemExtent: 550.0,
              itemCount: snapshot.data.documents.length,
              itemBuilder: (BuildContext context, int data) 
                //here I get the data from the userFeed colecction
                Post post = Post.fromDoc(snapshot.data.documents[data]);
                return Column(
                  children: <Widget>[
                    GestureDetector(
                      child: Container(
                        padding: EdgeInsets.symmetric(
                          horizontal: 16.0,
                          vertical: 10.0,
                        ),
                        child: Row(
                          children: <Widget>[
                            CircleAvatar(
                              radius: 25.0,
                              backgroundColor: Colors.grey,
                              backgroundImage: post.imageUrl.isEmpty
                                  ? AssetImage(
                                      'assets/images/user_placeholder.jpg')
                                  : CachedNetworkImageProvider(post.imageUrl),
                            ),
                            SizedBox(width: 8.0),
                            Text(
                              post.caption,
                              style: TextStyle(
                                fontSize: 18.0,
                                fontWeight: FontWeight.w600,
                              ),
                            ),
                          ],
                        ),
                      ),
                    ),
                    GestureDetector(
                      child: Stack(
                        alignment: Alignment.center,
                        children: <Widget>[
                          Container(
                            height: MediaQuery.of(context).size.width,
                            decoration: BoxDecoration(
                              image: DecorationImage(
                                image:
                                    CachedNetworkImageProvider(post.imageUrl),
                                fit: BoxFit.cover,
                              ),
                            ),
                          ),
                        ],
                      ),
                    ),
                  ],
                );
              ,
            );
          ,
        ),
      ),
    );
  

2020 年 5 月 22 日更新我如何解决问题 感谢用户 griffins,他帮助我解决了这个问题。

这就是我的工作:

我嵌套了我的 StreamBuilder,所以我可以同时使用 2 个流

 return StreamBuilder(
      stream: _stream,
      builder: (context, snapshot1) 
        return StreamBuilder(
          stream: _stream2,
          builder: (context, snapshot2) 
            if (!snapshot2.hasData) return const Text('Loading...');
            if (!snapshot1.hasData) return const Text('Loading...');
            return ListView.builder(
              itemExtent: 550.0,
              itemCount: snapshot2.data.documents.length,
              itemBuilder: (BuildContext context, int data) 
                User user = User.fromDoc(snapshot2.data.documents[data]);
                Post post = Post.fromDoc(snapshot1.data.documents[data]);
                return buildbody(user, post, context);
              ,
            );
          ,
        );
      ,
    );

【问题讨论】:

【参考方案1】:

您可以让您的身体获取一个小部件ListView 并且对于Listview 孩子拥有您的两个列表。

例子

body: ListView(
          children: <Widget>[
           ---list1----

            --list2-----   
          ]);

或者您可以使用自定义滚动视图

return new Scaffold(
    appBar: new AppBar(
        title: new Text("Project Details"),
        backgroundColor: Colors.blue[800]),
    body:
    new CustomScrollView(
        slivers: <Widget>[
          new SliverPadding(padding: const EdgeInsets.only(left: 10.0,right: 10.0,
              top: 10.0,bottom: 0.0),
            sliver: new SliverList(delegate:
            new SliverChildListDelegate(getTopWidgets())),
          ),
          new SliverPadding(padding: const EdgeInsets.all(10.0),
              sliver: new SliverList(delegate: new SliverChildListDelegate(
                  getSfListTiles()
              ))),
          new SliverPadding(padding: const EdgeInsets.all(10.0),
              sliver: new SliverList(delegate: new SliverChildListDelegate(
                  getWorkStatementTiles()
              ))),
        ]
    )

);

更新 来自@Rémi Rousseletanswer可以嵌套StreamBuilder

    StreamBuilder(
  stream: stream1,
  builder: (context, snapshot1) 
    return StreamBuilder(
      stream: stream2,
      builder: (context, snapshot2) 
        // do some stuff with both streams here
      ,
    );
  ,
)

【讨论】:

所有选项都不起作用,第一个给我一个错误,第二个不允许我添加小部件,但是谢谢 兄弟,非常感谢,我能够解决这个问题。谢谢! 太棒了,如果您将此标记为未来访问者的答案,那就太好了。

以上是关于如何使用 Flutter 从 Firebase 中的两个集合中获取数据的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Firebase 实时数据库中获取数据到 Flutter 中的列表中?

如何使用 graphql 从 Firebase 使用 Flutter 从 Cloud Firestore 获取数据?

如何使用 Flutter 中的 UserID 从 Firebase Firestore 检索数据?

Flutter 在使用 StreamBuilder 从 firebase 加载数据之前显示红色错误屏幕,如何解决?

如何从 Flutter 应用程序中删除 firebase 用户? [复制]

如何从 Flutter 中的 Firebase 的 UID 获取任何用户的电子邮件? [复制]