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

时间:2020-05-21 13:19:57

标签: firebase flutter google-cloud-firestore stream-builder

这是我的问题:

我有一个ListPost StatefulWidget,我想在其中显示包含用户帐户图像,用户名和用户帖子图像(类似于Facebook feed)的窗口小部件列表,但是,我已经开始我需要从Firebase中的两个不同集合中获取数据的要点(请参见下面的firebase集合图像)。

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

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

这是Firebase图片

enter image description here

这是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 个答案:

答案 0 :(得分:0)

您可以使自己带有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 Rousselet answer,您可以嵌套StreamBuilder

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