如何在Flutter中嵌套StreamBuilders?

问题描述 投票:1回答:2

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

我有一个流,从Firestore获得文档的集合,和一个流,依赖于数据从第一得到一个文档的子集合。我想把这些流合并成一个流,但它们需要嵌套,因为每个文档都有自己的文档子集。

流1(从FireStore中得到一个习惯的集合)。

Stream<List> getHabits(){
  final Stream<QuerySnapshot> documents = Firestore.instance
    .collection("users")
    .document('VtL1sxOoCOdJaOTT87IbMRwBe282')
    .collection("habits")
    .snapshots();

  Stream<List> data = documents.map((doc) {
    List data;
    final documents = doc.documents;
    ///Maybe this would work to get history of each doc? 
    for(int i = 0; i < documents.length; i++){
      ///not sure what to do
      getHistory(documents[i].documentID, DateTime.utc(2019,7,7), DateTime.now());
    }

    data = documents.map((documentSnapshot) => documentSnapshot).toList();

    return data;
  });

  return data;
}

流2 (在流1中调用,从FireStore中获取) DocumentID 作为参数,得到文档的子集)。)

Stream<List> getHistory(String id, DateTime start, DateTime end) async* {
  await for (QuerySnapshot querySnapshot in Firestore.instance
    .collection("users")
    .document('VtL1sxOoCOdJaOTT87IbMRwBe282')
    .collection("habits")
    .document(id)
    .collection("history")
    .where('day', isGreaterThanOrEqualTo: start)
    .where('day', isLessThanOrEqualTo: end)
    .snapshots()) {

      List history;
      final documents = querySnapshot.documents;

      history = documents.map((documentSnapshot) => documentSnapshot).toList();

      yield history;
    }
}

有什么办法可以帮助我把这些流以嵌套的格式组合成一个流,以便与... 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,
    );

  },
),

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

flutter dart stream google-cloud-firestore
2个回答
1
投票

我已经做了类似的事情,简单地使用嵌套 StreamBuilders. 根据你想让你的 Widget的组织结构,你可以在外部的 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());
    },
  );
}

1
投票

试着把你的数据流合并到类似 Observable.zip2(stream1,stream2,zipper)Observable.combineLatest2(streamA, streamB, combiner).

欲了解更多信息,请查看以下内容 岗位

© www.soinside.com 2019 - 2024. All rights reserved.