Home > front end >  Flutter Streambuilder stream inconsistent FirebaseFirestore snapshot data
Flutter Streambuilder stream inconsistent FirebaseFirestore snapshot data

Time:10-08

Retrieving shopping cart items my snapshot data is inconsistent. When one item is in cart I get this correctly formatted result:

{1111111111111: 1, PriceSmart: 540.0}

When two items in cart, and second item is also "PriceSmart", I get an error because returns this result:

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

and should be:

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

This is my firebase data structure:

First cart item:

enter image description here

Second cart item:

enter image description here

Basically is combining the "seller" (PriceSmart), when I need to return complete data from each cart item, otherwise I get an error as soon as I have more than one item in cart and seller is the same.

Please check the Stream in my code and see what is wrong with this implementation:

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');
          }
        });
  }
}

CodePudding user response:

Without seeing more of your code, it's hard to make an example to exactly fit your specification, and the error you're getting doesn't match the code you posted, but, broadly, you need to:

  • move the Stream outside your build function and into initState
  • process each snapshot one at a time
  • stay away from processing the data in your build widget
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,
        );
    }
  );
}
  • Related