【问题标题】:Merging multiple firebase stream in flutter在颤动中合并多个firebase流
【发布时间】:2021-07-16 11:33:44
【问题描述】:

伙计,将多个 Firebase 流合并到一个流是一个真正的问题。有人应该为此写一篇文章或一个简单的视频教程。使用 StreamGroup、FlatMap()、Rx.combineLatest、StreamZip 或 CombineLatestesStream。我从昨天开始尝试解决这个问题,但我无法获得明确的指导。

class CartPage extends StatefulWidget{
   @override
   _CartPageState createState() => _CartPageState();
}
class _CartPageState extends State<CartPage> {
   
   // a firebase collection for all items
   Stream stream1 = EcommerceApp.firestore
    .collection("items")
    .where("shortInfo",
        whereIn: EcommerceApp.sharedPreferences
            .getStringList(EcommerceApp.userCartList))
    .snapshots();

   // a firebase collection for flash sales items
   Stream stream2 = EcommerceApp.firestore
    .collection("flashitem")
    .where("shortInfo",
        whereIn: EcommerceApp.sharedPreferences
            .getStringList(EcommerceApp.userCartList))
    .snapshots();

   List<QuerySnapshot> getList(QuerySnapshot list1) {
   List<QuerySnapshot> result = [];
   (list1 as List).forEach((element) {
     result.add(element);
    });
     return result;
   }

 @override
 Widget build(BuildContext context) {

  Stream combineStream = Rx.combineLatest2(streamA, streamB, (a, b) => [a, b]);


   return Scaffold(
    appBar: MyAppBar(),
    body:CustomScrollView(
      slivers: [
        SliverToBoxAdapter(
          child: Container(
            height: 10.0,
          ),
        ),
       StreamBulder(
       stream: combineStream,
        builder: (context, snapshot) {
              if (!snapshot.hasData) {
                return SliverToBoxAdapter(
                  child: Center(
                    child: circularProgressBar(),
                  ),
                );
              } else {
              List<QuerySnapshot> _list = [];
                _list.addAll(getList(snapshot.data[0]));
                _list.addAll(getList(snapshot.data[1]));
                if (_list.length == 0) {
                } else {
                  return SliverList(
                    delegate: SliverChildBuilderDelegate(
                      (context, index) {
                        ProductModel model = ProductModel.fromJson(
                           _list[index].docs[index].data());

                        return cartSourceInfo(model, context,
                            removeCartFunction: () =>
                                removeItemFromUserCart(model.shortInfo));
                      },
                      childCount: childCount: snapshot.hasData ? _list.length : 0,
                    ),
                  );
                }
              }
            }    
       )
    );
 }
}

这里的大部分答案是使用 rxdart 中已废弃的 Observable 库,当我尝试使用相同的语法来解决使用 Rx.latestCombine2 时,没有数据流。当我尝试将 list 类型的 querySnapshot 传递给流 Stream 时,我收到了一批错误:

类“列表”没有实例获取器“文档”。 接收方:“_GrowableList”的实例(长度:2) 尝试调用:docs

请告诉我如何将这两个 firebase 流嵌套到 ome 中,或者如何使用 Rx.combineLatest2 方法来解决这个问题。

【问题讨论】:

  • 问题是我不知道如何将多个流合并为一个流。我想我错过了一些东西。

标签: firebase flutter rxdart


【解决方案1】:

语法看起来是正确的,但是当尝试访问每个流的数据时,您必须通过索引来访问它,因为快照基本上是一个列表

所以要访问 stream1 和 stream2 的快照,应该像这样访问它

分别为snapshot.data[0].docssnapshot.data[1].docs

您可以将两个流合并并在 Ui 中显示列表,并确保根据 snapshot.data[index].docs 的类型分配适当的类型 T


 List<QuerySnapshot> combineLists(
      List<QuerySnapshot> list1, List<QuerySnapshot> list2) {
    List<QuerySnapshot> result = [];
    list1.forEach((element) {
      result.add(element);
    });
    list2.forEach((element) {
      result.add(element);
    });
    return result;
  }

StreamBulder(
 ​stream: combineStream,
 ​builder: (context, AsyncSnapshot<List<QuerySnapshot>> snapshot) {
   ​if (!snapshot.hasData) {
      ​return SliverToBoxAdapter(
        ​child: Center(
          ​child: circularProgressBar(),
          ​),
        ​);
      ​} else {​
         final List<QuerySnapshot> _list=[];
         final List<QuerySnapshot> combineSnapshot =
                    combineLists(snapshot.data[0], snapshot.data[1]);
         ​if (_list.length == 0) {
            ​return addItems();
         ​} else {
             return SliverList(
                ​delegate: SliverChildBuilderDelegate(
                (context, index) {
                     ProductModel model = ProductModel.fromJson(
                     _list[index].data());
                 return cartSourceInfo(model, context, removeCartFunction: 
                    () => removeItemFromUserCart(model.shortInfo));
                 ​},
                 childCount:_list.length,
                 ),
               );
           ​}
        }
   }

【讨论】:

  • 到目前为止,我已经设法访问了两个流的快照。非常感谢。但是现在我如何更新我的 childCount 来计算两个流的长度。我已经尝试过 (snapshot.data[0].docs.length + snapshot.data[1].docs.length) 但我得到 - RangeError (index): Invalid value: Only valid value is 0: 1
  • cna 您是否在您的问题中添加了更多详细信息,您想在 Ui 中显示哪些数据、来自哪个集合以及集合的结构是什么?
  • 你想在一个列表中显示两个流数据吗?
  • 根据您上面的回答,在 SliverchildBuilderDelegate 内部,我创建了两个对象 ProductModel model = ProductModel.fromJson(snapshot.data[0].docs[index].data()); ProductModel flashSalemodel = ProductModel.fromJson(snapshot.data[1].docs[index].data()); 当我使用一个对象时它运行良好,但是当我同时使用两个对象时我得到 RangeError (index): Invalid value: Only valid value is 0: 1
  • 我已经更新了答案检查,只是分配了一个属性类型 T
猜你喜欢
  • 1970-01-01
  • 2021-08-09
  • 2021-10-11
  • 2018-12-15
  • 2021-12-10
  • 2020-12-09
  • 2021-04-14
  • 2019-04-02
  • 1970-01-01
相关资源
最近更新 更多