【问题标题】:Flutter merge two firestore streams into a single streamFlutter 将两个 Firestore 流合并为一个流
【发布时间】:2019-04-16 16:22:45
【问题描述】:

我只是想执行一个“或”运算并将两个查询的两个结果放到一个流中。

这是我的单流代码

 StreamBuilder(
    stream: Firestore.instance
        .collection('list')
        .where('id', isEqualTo: 'false')
        .orderBy('timestamp')
        .snapshots(),
    builder: (context, snapshot) {
      if (!snapshot.hasData)
        return Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Center(
              child: CircularProgressIndicator(),
            )
          ],
        );
      if (snapshot.data.documents.length == 0)
        return const Center(
          child: Text(
            "Not Available",
            style: TextStyle(fontSize: 30.0, color: Colors.grey),
          ),
        );
      return ListView.builder(
        padding: EdgeInsets.all(5.0),
        key: Key(randomString(20)),
        itemCount: snapshot.data.documents.length,
        itemBuilder: (BuildContext context, int index) {
          return ListCard(snapshot.data.documents[index]);
        },
      );
    }),

现在我想将两个流提供给同一个流构建器,而不是单个流。

我尝试了 StreamGroup,但自从 Widgets 重建后它无法正常工作

StreamGroup.merge([streamOne, streamTwo]).asBroadcastStream();

我也尝试了以下方法

 Stream<List<DocumentSnapshot>> searchResult()  {
List<Stream<List<DocumentSnapshot>>> streamList = [];

Firestore.instance
    .collection('room-list')
    .where('id', isEqualTo: 'false')
    .snapshots()
    .forEach((snap) {
  streamList.add(Observable.just(snap.documents));
});

Firestore.instance
    .collection('room-list')
    .where('id', isEqualTo: 'pending')
    .snapshots()
    .forEach((snap) {
  streamList.add(Observable.just(snap.documents));
});

var x = Observable.merge(streamList)
    .scan<List<DocumentSnapshot>>((acc, curr, i) {
  return acc ?? <DocumentSnapshot>[]
    ..addAll(curr);
});
return x;
}

这里我得到了错误,应该至少有一个流要合并。这是因为 Observable.merge(streamList) 在项目添加到 streamList 之前被调用。

我只是想将两个查询的两个结果合并到一个流中。

【问题讨论】:

  • 你能链接.where() 调用吗?
  • 你可以链接,它会变成一个 AND 运算符而不是 OR 这就是问题所在。一个简单的 OR 在哪里可以解决这个问题,但这样的选项不可用
  • @PraneethDhanushkaFernando 你设法解决了这个问题吗?
  • @hadooper nope 兄弟仍在苦苦挣扎
  • 我也遇到了同样的问题,你是怎么解决这个问题的

标签: firebase merge flutter google-cloud-firestore rxdart


【解决方案1】:

这应该可行。

//Change your streams here
    Stream<List<QuerySnapshot>> getData() {
        Stream stream1 = Firestore.instance.collection('list').where('id', isEqualTo: 'false').orderBy('timestamp').snapshots();
        Stream stream2 = Firestore.instance.collection('list').where('id', isEqualTo: 'true').orderBy('timestamp').snapshots();
        return StreamZip([stream1, stream2]);
      }


  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      body: StreamBuilder(
          stream: getData(),
          builder: (BuildContext context, AsyncSnapshot<List<QuerySnapshot>> snapshot1) {

            List<QuerySnapshot> querySnapshotData =  snapshot1.data.toList();

            //copy document snapshots from second stream to first so querySnapshotData[0].documents will have all documents from both query snapshots
            querySnapshotData[0].documents.addAll(querySnapshotData[1].documents);

            if (querySnapshotData[0].documents.isEmpty)
              return Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Center(
                    child: CircularProgressIndicator(),
                  )
                ],
              );
            if (querySnapshotData[0].documents.length == 0)
              return const Center(
                child: Text(
                  "Not Available",
                  style: TextStyle(fontSize: 30.0, color: Colors.grey),
                ),
              );

            return new ListView(
                children: querySnapshotData[0].documents.map((DocumentSnapshot document){
                 // put your logic here. You will have access to document from both streams as "document" here
                  return new ListCard(document);
                }).toList()
            );
          }
      ),
    );
  }

希望对你有帮助!!!

【讨论】:

  • @PraneethDhanushkaFernando 请试试这个,让我知道它是否有效。谢谢
  • StreamZip 不能用于这个兄弟。它用于组合彼此所属的流,如标题和帖子
  • 在这种情况下,您将需要嵌套的流构建器
  • 这适用于我的特殊情况。我整天都在努力,但我还是偶然发现了你的答案。谢谢@m-bhole,来自未来 :)
  • 确保将异步添加到您的依赖项中
【解决方案2】:

我不确定你为什么要使用 forEach 和 Observable.just()。

您可以直接合并两个 Firestore 流,例如:

Observable.merge([stream1, stream2]).pipe(combineStream);

stream1/2 只是您的 Firestore 快照。

【讨论】:

  • combinStream 是从哪里来的?
  • 只需为 combineStream 创建一个新的 PublishSubject 或 StreamContoller。
  • 我尝试了您的建议,但失败了。当我尝试调用 merge 时,stream1 是一个 firestore 查询快照,它表示我正在尝试合并一个空流。这是因为 stream1 和 stream2 在等待 firestore 时尚未初始化。如何确保在调用合并之前初始化 stream1 和 sream2?
【解决方案3】:

我使用 RxDart 包来组合两个流,如下所示

RxDart - CombineLatestStream

final Stream<DocumentSnapshot> user = Firestore.instance
        .collection("users")
        .document(firebaseUser.uid)
        .snapshots();

    final Stream<QuerySnapshot> cards =
        Firestore.instance.collection("cards").snapshots();

    CombineLatestStream.list([user, cards]).listen((data) {
      add(LoadedHomeEvent(
        data.elementAt(0),
        data.elementAt(1),
      ));
    });

【讨论】:

  • 你用过CombineLatestStream....那么进一步的代码是什么?请分享完整的代码,以便其他用户和我可以了解发生了什么?它只是一个请求:) 谢谢。
【解决方案4】:

好吧,我迟到了,但我会把它放在那里。

您可以像这样在查询中添加 whereIn 子句:

Firestore.instance.collection("collection_name").where("field",whereIn:["false","true"]).snapshots();

【讨论】:

  • 这根本行不通!
  • 他们可能改变了方法。
猜你喜欢
  • 2020-03-20
  • 1970-01-01
  • 2023-03-26
  • 1970-01-01
  • 2020-03-27
  • 2021-03-26
  • 2020-03-25
  • 2018-07-30
  • 1970-01-01
相关资源
最近更新 更多