首页 > 解决方案 > Flutter Streambuilder 流不一致的 FirebaseFirestore 快照数据

问题描述

检索购物车项目我的快照数据不一致。当购物车中有一件商品时,我会得到格式正确的结果:

{1111111111111: 1, PriceSmart: 540.0}

当购物车中有两个项目,第二个项目也是“PriceSmart”时,我得到一个错误,因为返回这个结果:

{1111111111111: 1, PriceSmart: 300.0, 5555555555555: 1}

应该是:

{1111111111111: 1, PriceSmart: 540.0, 5555555555555: 1, PriceSmart: 300.0}

这是我的 Firebase 数据结构:

第一个购物车项目:

在此处输入图像描述

第二个购物车项目:

在此处输入图像描述

基本上是结合“卖家”(PriceSmart),当我需要从每个购物车项目返回完整数据时,否则一旦我在购物车中有多个项目并且卖家是相同的,我就会收到错误。

请检查我的代码中的流,看看这个实现有什么问题:

class PriceUpdaterWidget extends StatefulWidget {
  const PriceUpdaterWidget({
    Key? key,
    required this.loginService,
    required this.code,
    required this.itemSubCategory,
  }) : super(key: key);
  final LoginService loginService;
  final String? code;
  final SubCategory? itemSubCategory;

  _PriceUpdaterWidgetState createState() => _PriceUpdaterWidgetState();
}

class _PriceUpdaterWidgetState extends State<PriceUpdaterWidget> {
  @override
  Widget build(BuildContext context) {
    CategorySelectionService catSelection =
        Provider.of<CategorySelectionService>(context, listen: false);

    Stream<DocumentSnapshot> priceDocStream = FirebaseFirestore.instance
        .collection('shoppers')
        .doc(widget.loginService.loggedInUserModel!.uid)
        .collection("cartItems")
        .doc(widget.code)
        .snapshots();
    return StreamBuilder<DocumentSnapshot>(
        stream: priceDocStream,
        builder:
            (BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
          
          SellerNameService isSellerName =
              Provider.of<SellerNameService>(context, listen: false);

          var sellerName = isSellerName.isSellerName;

          if (snapshot.data != null) {
            return Text(
              snapshot.data![sellerName].toStringAsFixed(2),
              textAlign: TextAlign.center,
            );
          } else {
            return Text('No Data');
          }
        });
  }
}

标签: firebaseflutterdartgoogle-cloud-firestore

解决方案


如果没有看到更多代码,很难创建一个完全符合您的规范的示例,并且您得到的错误与您发布的代码不匹配,但是,从广义上讲,您需要:

  • 将您的功能移到Stream外部buildinitState
  • 一次处理每个快照
  • 远离处理构建小部件中的数据
class PriceUpdaterWidget extends StatefulWidget {
  final String login, code;
  const PriceUpdaterWidget(this.login, this.code);

  @override
  _PriceUpdaterWidgetState createState() => _PriceUpdaterWidgetState ();
}

class _PriceUpdaterWidgetState extends State<PriceUpdaterWidget> {
  Stream<DocumentSnapshot> priceStream;  // only one stream per widget

  @override
  void initState() {
    super.initState();
    priceStream = FirebaseFirestore.instance  // set the stream once
      .collection("shoppers")
      .doc(widget.login)
      .collection("cartItems")
      .doc(widget.code)
      .snapshots();
  }

  @override
  Widget build(BuildContext context) => StreamBuilder<DocumentSnapshot>(
    stream: priceStream,
    builder: (context, snapshot) {
      const String sellerName = "PriceSmart";
      return snapshot.data == null 
        ? const Text("No data") 
        : Text(
          snapshot.data[sellerName].toStringAsFixed(2),
          textAlign: TextAlign.center,
        );
    }
  );
}

推荐阅读