Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Flutter 你怎么能在颤振中筑巢?_Flutter_Dart_Stream_Google Cloud Firestore - Fatal编程技术网

Flutter 你怎么能在颤振中筑巢?

Flutter 你怎么能在颤振中筑巢?,flutter,dart,stream,google-cloud-firestore,Flutter,Dart,Stream,Google Cloud Firestore,我有两个流,我需要结合起来构建一个小部件,但不同于我看到的其他问题,我需要嵌套我的流 我有一个从Firestore获取文档集合的流,还有一个依赖于第一个流的数据来获取文档子集合的流。我想将它们合并到一个流中,但它们需要嵌套,因为每个文档都有自己的文档子集合 流1(从FireStore获取习惯集合): 如果您能帮助我将这些流以嵌套格式组合成一个流,以便与flift中的StreamBuilder一起使用,我将不胜感激 编辑 我不确定我是否朝着正确的方向工作,但我已经尝试实现了spenster的解决方

我有两个流,我需要结合起来构建一个小部件,但不同于我看到的其他问题,我需要嵌套我的流

我有一个从Firestore获取文档集合的流,还有一个依赖于第一个流的数据来获取文档子集合的流。我想将它们合并到一个流中,但它们需要嵌套,因为每个文档都有自己的文档子集合

流1(从FireStore获取习惯集合):

如果您能帮助我将这些流以嵌套格式组合成一个流,以便与flift中的
StreamBuilder
一起使用,我将不胜感激

编辑 我不确定我是否朝着正确的方向工作,但我已经尝试实现了spenster的解决方案,除了上述功能之外,这就是我目前所拥有的

StreamBuilder<List>(
  stream: getHabits(),
  initialData: [],
  builder: (context, snapshot) {
    List<UserHabit> habits = [];
    List<Widget> test = List.generate(snapshot.data.length, (index){
      List<History> history = [];
      DocumentSnapshot doc = snapshot.data[index];
      return StreamBuilder(
        stream: getHistory(doc.documentID, DateTime.utc(2019,7,7), DateTime.now()),
        builder: (context, snapshot) {
          if (snapshot.hasError)
            return new Text('Error: ${snapshot.error}');
          switch (snapshot.connectionState) {
            case ConnectionState.waiting: return new Text('Loading...');
            default:
              if(!snapshot.data.isEmpty){ //history collection exists
                for(int i = 0; i < snapshot.data.length; i++){
                  //add to history
                  history.add(History(
                    day: snapshot.data[i]['day'].toDate(), 
                    dateCompleted: snapshot.data[i]['dateCompleted'].toDate(), 
                    morning: snapshot.data[i]['morning'],
                    afternoon: snapshot.data[i]['afternoon'],
                    evening: snapshot.data[i]['evening'],
                    anytime: snapshot.data[i]['anytime'],
                  ));
                }
              }
              habits.add(UserHabit(
                name: doc['habit'],
                color: doc['color'],
                icon: doc['icon'],
                repeat: doc['repeat'],
                daily: doc['daily'],
                weekly: doc['weekly'],
                monthly: doc['monthly'],
                time: doc['time'],
                history: history,
              ));
              print(habits); //returns each iteration of assembling the list
              return Text("i dont want to return anything");
          }
        },
      );
      }
    );
    print(habits); //returns empty list before anything is added
    return Column(
      children: test,
    );

  },
),
StreamBuilder(
流:getHabits(),
初始数据:[],
生成器:(上下文,快照){
列出习惯=[];
列表测试=列表.generate(snapshot.data.length,(索引){
列表历史=[];
DocumentSnapshot doc=snapshot.data[索引];
返回流生成器(
流:getHistory(doc.documentID,DateTime.utc(2019,7,7),DateTime.now()),
生成器:(上下文,快照){
if(snapshot.hasError)
返回新文本('Error:${snapshot.Error}');
交换机(快照.连接状态){
case ConnectionState.waiting:返回新文本('Loading…');
违约:
如果(!snapshot.data.isEmpty){//历史记录集合存在
对于(int i=0;i

UserHabits和History类可以共享,但它们只是分配类型并允许轻松访问的基本类

我简单地使用嵌套的
StreamBuilders
做了类似的事情。根据您希望
小部件的组织方式,您可以在外部
StreamBuilder
中创建流。根据您的澄清意见,这是一种可能性:

@override
Widget build(BuildContext context) {

  var habits = Firestore.instance
    .collection("users")
    .document('VtL1sxOoCOdJaOTT87IbMRwBe282')
    .collection("habits")
    .snapshots();

  return StreamBuilder<QuerySnapshot>(
    stream: habits,
    builder: (context, snapshot) {

      if (!snapshot.hasData)
        return Text("Loading habits...");

      return ListView(children: snapshot.data.documents.map((document) {

        var query = Firestore.instance
          .collection("users")
          .document('VtL1sxOoCOdJaOTT87IbMRwBe282')
          .collection("habits")
          .document(document.documentID)
          .collection("history")
          .where('day', isGreaterThanOrEqualTo: start)
          .where('day', isLessThanOrEqualTo: end)
          .snapshots();

        return StreamBuilder<QuerySnapshot>(
          stream: query,
          builder: (context, snapshot) {

            if (!snapshot.hasData) return Text("Loading...");

            // right here is where you need to put the widget that you
            // want to create for the history entries in snapshot.data...
            return Container();
          },
        );
      }).toList());
    },
  );
}
@覆盖
小部件构建(构建上下文){
var=Firestore.instance
.收集(“用户”)
.document('VtL1sxOoCOdJaOTT87IbMRwBe282')
.收集(“习惯”)
.快照();
返回流生成器(
溪流:习惯,
生成器:(上下文,快照){
如果(!snapshot.hasData)
返回文本(“加载习惯…”);
返回ListView(子项:snapshot.data.documents.map((文档){
var query=Firestore.instance
.收集(“用户”)
.document('VtL1sxOoCOdJaOTT87IbMRwBe282')
.收集(“习惯”)
.document(document.documentID)
.收藏(“历史”)
.其中('day'大于或等于:开始)
.where('day',isLessThanOrEqualTo:end)
.快照();
返回流生成器(
流:查询,
生成器:(上下文,快照){
如果(!snapshot.hasData)返回文本(“正在加载…”);
//在这里,您需要放置您需要的小部件
//要为快照中的历史记录条目创建。数据。。。
返回容器();
},
);
}).toList());
},
);
}

尝试使用类似于
可观察的.zip2(stream1,stream2,zipper)
可观察的.combineLatest2(streamA,streamB,combiner)的东西来合并流。


有关更多信息,请查看此

谢谢!我会试一试,如果成功的话,我会把你的答案标记为正确!我感谢你花了这么多时间来回答!出于好奇,我有没有办法在
getHistory
StreamBuilder
中不返回任何内容?我需要使用
历史记录的列表
数据来查看事情是否完成,但我在
getHabits()
中只为每个项目构建了一个小部件。我还得到了以下错误
元素类型“Set”无法分配给列表类型“widget”。
如果您只想从历史记录中获取一个文档,然后您可以使用Firestore来选择它(比如在查询中使用.limit(1)),然后只构建一个小部件。这也顺便消除了你看到的另一个错误。我会看看是否可以更新答案……我想我已经设法让这个方法发挥作用了,但我觉得应该有一种方法可以嵌套流,而不需要嵌套StreamBuilder。或者firebase应该可以更容易地访问子文档哈哈。非常感谢您的时间,我会把这个标记正确的!我已经花了大约一周的时间研究这一难题。我喜欢它的发展方向,但第二个流取决于第一个流中某个项目的
documentID
。第二个流对于来自
StreamBuilder<List>(
  stream: getHabits(),
  initialData: [],
  builder: (context, snapshot) {
    List<UserHabit> habits = [];
    List<Widget> test = List.generate(snapshot.data.length, (index){
      List<History> history = [];
      DocumentSnapshot doc = snapshot.data[index];
      return StreamBuilder(
        stream: getHistory(doc.documentID, DateTime.utc(2019,7,7), DateTime.now()),
        builder: (context, snapshot) {
          if (snapshot.hasError)
            return new Text('Error: ${snapshot.error}');
          switch (snapshot.connectionState) {
            case ConnectionState.waiting: return new Text('Loading...');
            default:
              if(!snapshot.data.isEmpty){ //history collection exists
                for(int i = 0; i < snapshot.data.length; i++){
                  //add to history
                  history.add(History(
                    day: snapshot.data[i]['day'].toDate(), 
                    dateCompleted: snapshot.data[i]['dateCompleted'].toDate(), 
                    morning: snapshot.data[i]['morning'],
                    afternoon: snapshot.data[i]['afternoon'],
                    evening: snapshot.data[i]['evening'],
                    anytime: snapshot.data[i]['anytime'],
                  ));
                }
              }
              habits.add(UserHabit(
                name: doc['habit'],
                color: doc['color'],
                icon: doc['icon'],
                repeat: doc['repeat'],
                daily: doc['daily'],
                weekly: doc['weekly'],
                monthly: doc['monthly'],
                time: doc['time'],
                history: history,
              ));
              print(habits); //returns each iteration of assembling the list
              return Text("i dont want to return anything");
          }
        },
      );
      }
    );
    print(habits); //returns empty list before anything is added
    return Column(
      children: test,
    );

  },
),
@override
Widget build(BuildContext context) {

  var habits = Firestore.instance
    .collection("users")
    .document('VtL1sxOoCOdJaOTT87IbMRwBe282')
    .collection("habits")
    .snapshots();

  return StreamBuilder<QuerySnapshot>(
    stream: habits,
    builder: (context, snapshot) {

      if (!snapshot.hasData)
        return Text("Loading habits...");

      return ListView(children: snapshot.data.documents.map((document) {

        var query = Firestore.instance
          .collection("users")
          .document('VtL1sxOoCOdJaOTT87IbMRwBe282')
          .collection("habits")
          .document(document.documentID)
          .collection("history")
          .where('day', isGreaterThanOrEqualTo: start)
          .where('day', isLessThanOrEqualTo: end)
          .snapshots();

        return StreamBuilder<QuerySnapshot>(
          stream: query,
          builder: (context, snapshot) {

            if (!snapshot.hasData) return Text("Loading...");

            // right here is where you need to put the widget that you
            // want to create for the history entries in snapshot.data...
            return Container();
          },
        );
      }).toList());
    },
  );
}