You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中同时读取Firebase两个集合并对比销售额的问题

解决方案

1. 添加依赖

首先在pubspec.yaml中添加rxdart依赖,用于合并两个Firebase数据流:

dependencies:
  flutter:
    sdk: flutter
  rxdart: ^0.27.7
  cloud_firestore: ^4.12.0 # 确保与你的Firestore版本兼容

2. 修改数据流读取逻辑

保留原有单个集合读取方法,新增合并两个集合流的方法,同时获取当前选择月份和目标对比月份(示例为10.2022 Sales)的数据:

import 'package:rxdart/rxdart.dart';

// 原单个集合读取方法
static Stream<List<showSummaryReport>> read(String type) {
  final serviceCollection = FirebaseFirestore.instance.collection(type);
  return serviceCollection.snapshots().map((querySnapshot) =>
      querySnapshot.docs.map((e) => showSummaryReport.fromSnapshot(e)).toList());
}

// 新增合并两个集合流的方法
static Stream<List<List<showSummaryReport>>> readTwoCollections(String currentCollection, String compareCollection) {
  final currentStream = read(currentCollection);
  final compareStream = read(compareCollection);
  // 合并两个流,任一数据流更新时同步获取最新数据
  return CombineLatestStream.list([currentStream, compareStream]);
}

3. 修改StreamBuilder与UI展示

替换原单个流的监听逻辑,改为监听合并后的流,并匹配对应服务的对比数据:

Visibility(
  visible: gotChoice,
  child: StreamBuilder<List<List<showSummaryReport>>>(
      // 传入当前月份和对比月份的集合名称
      stream: readTwoCollections('${widget.expChoice.toString()} Sales', '10.2022 Sales'),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return Center(child: CircularProgressIndicator());
        }
        if (snapshot.hasError) {
          return Center(child: Text("出现错误"));
        }
        if (snapshot.hasData) {
          final currentData = snapshot.data![0]; // 当前月份数据
          final compareData = snapshot.data![1]; // 对比月份数据

          return Expanded(
            child: ListView.builder(
                itemCount: currentData.length,
                itemBuilder: (context, index) {
                  final service = currentData[index];
                  // 根据服务名称匹配对比数据中的对应条目
                  final compareService = compareData.firstWhere(
                    (item) => item.serviceName == service.serviceName,
                    orElse: () => showSummaryReport(serviceName: service.serviceName, sales: 0), // 未匹配到的默认值
                  );

                  return Column(
                    children: [
                      ListTile(
                          onTap: () {
                            Navigator.push(context, MaterialPageRoute(builder: (context)=>
                                selectedDetailReport(detail: '${service.serviceName} Sales',
                                  month: widget.expChoice.toString(),)));
                          },
                          title: Card(
                            color: 'CAF0F8'.toColor(),
                            shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
                            child: Table(
                              children: [
                                TableRow(children: [SizedBox(height: 10,), SizedBox(height: 10,)]),
                                TableRow(
                                    children: [
                                      Padding(
                                        padding: const EdgeInsets.fromLTRB(30,0,0,0),
                                        child: Text('服务名称 :',style: TextStyle(fontFamily: 'MonSemi', fontSize: 17)),
                                      ),
                                      Center(child: Text(service.serviceName.toString(),style: TextStyle(fontFamily: 'MonSemi', fontSize: 17))),
                                    ]
                                ),
                                TableRow(children: [SizedBox(height: 10,), SizedBox(height: 10,)]),
                                TableRow(
                                    children: [
                                      Padding(
                                        padding: const EdgeInsets.fromLTRB(30,0,0,0),
                                        child: Text('当月销售额 :',style: TextStyle(fontFamily: 'MonSemi', fontSize: 17)),
                                      ),
                                      Center(child: Text(service.sales.toString(),style: TextStyle(fontFamily: 'MonSemi', fontSize: 17))),
                                    ]
                                ),
                                TableRow(children: [SizedBox(height: 10,), SizedBox(height: 10,)]),
                                TableRow(
                                    children: [
                                      Padding(
                                        padding: const EdgeInsets.fromLTRB(30,0,0,0),
                                        child: Text('对比月份销售额 :',style: TextStyle(fontFamily: 'MonSemi', fontSize: 17)),
                                      ),
                                      // 展示对比数据的销售额
                                      Center(child: Text(compareService.sales.toString(),style: TextStyle(fontFamily: 'MonSemi', fontSize: 17))),
                                    ]
                                ),
                                TableRow(children: [SizedBox(height: 10,), SizedBox(height: 10,)]),
                              ],
                            ),
                          ),
                      ),
                    ],
                  );
                }),
          );
        }
        return Center(child: CircularProgressIndicator());
      }),
),

关键改动说明

  • 用CombineLatestStream合并两个Firestore数据流,保证任一集合数据更新时UI同步刷新
  • 通过firstWhere按服务名称匹配两个集合的数据,实现同服务销售额对比
  • 为未匹配到的数据设置默认值,避免UI报错
  • 替换原占位文本为对比月份的实际销售额数据

内容的提问来源于stack exchange,提问作者Lim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 15:01:04