【问题标题】:Flutter Firebase Merge Different Streams List ProblemFlutter Firebase 合并不同的流列表问题
【发布时间】:2022-01-20 14:48:12
【问题描述】:

我有一个这样的流的组合列表;

var Stream1 = _firestore
      .collectionGroup("Infos")
      .where('ID', whereIn: List1)
      .snapshots();
  var Stream2 = _firestore
      .collectionGroup("Infos")
      .where('ID', whereIn: List2)
      .snapshots();
  var Stream3 = _firestore
      .collectionGroup("Infos")
      .where('ID', whereIn: List3)
      .snapshots();
  
  List<Stream<QuerySnapshot>> combineList = [Stream1, Stream2, Stream3];

通过这种方法,我合并来自combineList 的流;

var totalStreams = StreamGroup.merge(combineList);

当我在 StreamBuilder 中使用 totalStreams 时,通常情况下,3 个合并流的所有结果都应该显示在 StreamBuilder 中,但我只在 StreamBuilder 中显示最后一个流(Streams3)的数据。

【问题讨论】:

标签: firebase flutter


【解决方案1】:

使用这个包https://pub.dev/packages/async,如下所示。

import 'package:async/async.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';

class InfosWidget extends StatefulWidget {
  const InfosWidget({Key? key}) : super(key: key);

  @override
  State<InfosWidget> createState() => _InfosWidgetState();
}

class _InfosWidgetState extends State<InfosWidget> {
  late Stream<List<List<Infos>>> _myStreamInfos;

  @override
  void initState() {
    super.initState();

    _myStreamInfos = StreamZip(
      [
        FirebaseFirestore.instance
            .collectionGroup("Infos")
            .where("id", whereIn: ["id1", "id2"])
            .snapshots()
            .map((query) =>
                query.docs.map((map) => Infos.fromMap(map.data())).toList()),
        FirebaseFirestore.instance
            .collectionGroup("Infos")
            .where("id", whereIn: ["id1", "id2"])
            .snapshots()
            .map((query) =>
                query.docs.map((map) => Infos.fromMap(map.data())).toList()),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<List<List<Infos>>>(
        stream: _myStreamInfos,
        builder: (context, snapshot) {
          if (!snapshot.hasData) {
            return const SizedBox();
          }
          final listInfos = <Infos>[];
          for (final info in snapshot.data!) {
            listInfos.addAll(info);
          }

          return Container();
        });
  }
}

@immutable
class Infos {
  final String id;
  final String something;

  const Infos({required this.id, required this.something});

  Map<String, dynamic> toMap() {
    return {
      'id': id,
      'something': something,
    };
  }

  factory Infos.fromMap(Map<String, dynamic> map) {
    return Infos(
      id: map['id'] as String,
      something: map['something'] as String,
    );
  }
}

【讨论】:

  • 我不能这样做,因为 combineList 元素(流的数量)是动态的。所以有时它可以包括 2 有时 1 有时 4 个流。
  • 所以使用 for 循环:" for(list in asyncsnapshot.data){ listOfDocumentSnapshot.addAll(list); }" 类似的东西。
  • 列表 查询快照; for (int i = 0; i 文档快照 = []; querySnapshot.forEach((query) { documentSnapshot.addAll(query.docs); });
  • 我试过了,但这不起作用。你能看看这个解决方案有什么问题吗?
  • 类“_JsonQuerySnapshot”没有实例方法“[]”。接收方:“_JsonQuerySnapshot”实例尝试调用:[](0) 我收到此错误。
【解决方案2】:

要合并流,我可以建议你使用 rxdart 的CombineLatestStream。 每次其中一个流发出一个新事件时,StreamBuilder 都会构建。 返回的 snapshot.data 是每个流的最新元素的列表。

当任何一个源流序列发出一个项目时,combiner 函数将指定的 Streams 合并为一个 Stream 序列。

在所有 Streams 至少发出一项之前,Stream 不会发出。 如果提供的流之一为空,则生成的序列将在不发出任何项目或使用组合器的情况下完成 功能。

这里是代码示例:

StreamBuilder( 
stream: CombineLatestStream.list([ 
  stream0, 
  stream1, 
]), 
builder: (context, snapshot) { 
  final data0 = snapshot.data[0]; 
  final data1 = snapshot.data[1]; 
})

另一个可能帮助您合并流的构造函数是:Merge.

指定流的元素被展平为单个流序列。 如果一个或多个指定的流为空,则生成的序列完成而不发射任何项目。

示例代码:

static Stream<T> merge<T>(Iterable<Stream<T>> streams) =>
    MergeStream<T>(streams);

这是一个link,它显示了每个构造函数的工作原理图。

【讨论】:

  • 我已经解决了这个问题,你可以查看我的答案。
  • 很高兴知道您找到了解决方案,我看到您使用了 combineLatestStream,如果我的回答帮助您解决了问题,请告诉我。另外,我建议您更新此当前问题并添加您上传解决方案的链接。
  • 解决问题后我才看到你提出了类似的方法。但这是我的问题的接近解决方案。
  • 在评论部分,我添加了我解释问题答案的链接,我不知道我还能如何更新问题。
猜你喜欢
  • 2022-01-21
  • 1970-01-01
  • 2021-12-11
  • 2020-03-21
  • 2010-10-31
  • 2020-11-10
  • 2011-08-26
  • 2022-12-14
  • 2022-06-29
相关资源
最近更新 更多