【问题标题】:How to get a sum of number from streambuilder如何从streambuilder获得数字总和
【发布时间】:2022-06-11 03:23:47
【问题描述】:

我正在尝试从购物车中的 streambuilder 获取总价。并将其分配给双精度。问题是当我第一次点击购物车时,总价显示为零。当我刷新页面时,总数才会正确显示。我相信double price = 0; 的初始声明是导致它在第一次打开购物车时在购物车屏幕中带来零值的原因。我已经在 google 上进行了一些搜索,这可能是因为我没有使用异步计算。我已经尝试过,但找不到合适的解决方案。

Shopping cart screen

这是购物车的代码

User? user = FirebaseAuth.instance.currentUser;
late String userid = user!.uid;

@override
CollectionReference<Object?> cart() {final CollectionReference cart = FirebaseFirestore.instance.collection('users').doc(userid).collection('cart');
return cart;
}

Widget bodySection(BuildContext context) {
return StreamBuilder(
    stream: cart().snapshots(),
    builder: (context, AsyncSnapshot<QuerySnapshot> streamSnapshot) {
      if (streamSnapshot.hasData) {
        return Padding(
          padding: EdgeInsets.symmetric(
              horizontal: getProportionateScreenWidth(20)),
          child: ListView.builder(
              physics: const AlwaysScrollableScrollPhysics(),
              itemCount: streamSnapshot.data!.docs.length,
              itemBuilder: (context, index) {
                final DocumentSnapshot documentSnapshot =
                    streamSnapshot.data!.docs[index];
                price = documentSnapshot['price'] + price; // to sums up the total price
                String imgurl = documentSnapshot['imgUrl'];
                return Padding(
                    padding: EdgeInsets.symmetric(vertical: 10),
                    child: Dismissible(
                      key: Key(documentSnapshot['id']),
                      direction: DismissDirection.endToStart,
                      onDismissed: (direction) {
                        setState(() {});
                      },
                      background: Container(
                        padding: EdgeInsets.symmetric(horizontal: 20),
                        decoration: BoxDecoration(
                          color: Color(0xFFFFE6E6),
                          borderRadius: BorderRadius.circular(15),
                        ),
                        child: Row(
                          children: [
                            Spacer(),
                            Icon(Icons.delete),
                          ],
                        ),
                      ),
                      child: Container(
                        padding:
                            EdgeInsets.all(getProportionateScreenWidth(8)),
                        decoration: BoxDecoration(
                          color: Colors.white,
                          borderRadius: BorderRadius.circular(15),
                        ),
                        child: Row(
                          children: [
                            SizedBox(
                              width: 88,
                              child: AspectRatio(
                                aspectRatio: 0.88,
                                child: Container(
                                  padding: EdgeInsets.all(
                                      getProportionateScreenWidth(5)),
                                  decoration: BoxDecoration(
                                      color: Colors.black,
                                      borderRadius:
                                          BorderRadius.circular(10),
                                      image: DecorationImage(
                                          image: NetworkImage(imgurl),
                                          fit: BoxFit.cover)),
                                ),
                              ),
                            ),
                            SizedBox(width: 20),
                            Column(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: [
                                Text(
                                  documentSnapshot['brand'] +
                                      " " +
                                      documentSnapshot['name'],
                                  style: TextStyle(
                                      color: Colors.black, fontSize: 16),
                                  maxLines: 2,
                                ),
                                SizedBox(height: 10),
                                Text.rich(
                                  TextSpan(
                                    text: "RM " +
                                        (documentSnapshot['price'])
                                            .toString(),
                                    style: TextStyle(
                                        fontWeight: FontWeight.w600,
                                        color: kPrimaryColor),
                                  ),
                                )
                              ],
                            ),
                            Spacer(),
                            Column(
                              children: [
                                SizedBox(
                                  height: 30,
                                ),
                                Text(
                                  "x 1",
                                  style: TextStyle(
                                      color: Colors.black, fontSize: 16),
                                ),
                              ],
                            ),
                          ],
                        ),
                      ),
                    ));
              }),
        );
      }
      return const Center(
        child: CircularProgressIndicator(),
      );
    });}

这是我要显示总价的代码

Widget billSection(BuildContext context) {
return Container(
  padding: EdgeInsets.symmetric(
    vertical: getProportionateScreenWidth(15),
    horizontal: getProportionateScreenWidth(30),
  ),
  // height: 174,
  decoration: BoxDecoration(
    color: Colors.white,
    borderRadius: BorderRadius.only(
      topLeft: Radius.circular(30),
      topRight: Radius.circular(30),
    ),
    boxShadow: [
      BoxShadow(
        offset: Offset(0, -15),
        blurRadius: 20,
        color: Color(0xFFDADADA).withOpacity(0.15),
      )
    ],
  ),
  child: SafeArea(
    child: Column(
      mainAxisSize: MainAxisSize.min,
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        SizedBox(height: getProportionateScreenHeight(20)),
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            Text.rich(
              TextSpan(
                  text: "Total:\n",
                  children: [
                    TextSpan(
                      text: "RM " + price.toString(), // display total price
                      style: TextStyle(
                          fontSize: 20,
                          color: Colors.black,
                          fontWeight: FontWeight.w700),
                    ),
                  ],
                  style: TextStyle(fontSize: 15)),
            ),
            SizedBox(
              width: getProportionateScreenWidth(190),
              child: SizedBox(
                width: double.infinity,
                height: getProportionateScreenHeight(56),
                child: TextButton(
                  style: TextButton.styleFrom(
                    shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(20)),
                    primary: Colors.white,
                    backgroundColor: kPrimaryColor,
                  ),
                  onPressed: () {},
                  child: Text(
                    "Check Out",
                    style: TextStyle(
                      fontSize: getProportionateScreenWidth(18),
                      color: Colors.white,
                    ),
                  ),
                ),
              ),
            ),
          ],
        ),
      ],
    ),
  ),
);

可变价格初始化

double price = 0;

【问题讨论】:

  • 我什至还不允许投票
  • 哦,好的,对不起。 XD

标签: flutter dart


【解决方案1】:

您试图在处理文档时将总和作为副作用发布,这是问题的根源。

更好的方法是将此流作为小部件中的字段:

FirebaseFirestore.instance
        .collection('users')
        .doc(userid)
        .collection('cart')
        .snapshots()

然后在您的 UI 中添加两个 StreamBuilder 小部件:一个用于文档本身,一个用于总和。

您还可以:

  1. listen() 到流中(例如在您的小部件的构造函数中),
  2. 计算其中的总和(通过循环遍历文档,但不渲染任何内容),
  3. 然后调用setState 将总和放入一个字段中,
  4. 最后,在 UI 中使用 FutureBuilderStreamBuilder 来呈现 sum 字段。

【讨论】:

  • Downvoter:您能否评论一下为什么这个答案没有用?
  • 对不起,你能给出一个示例代码吗?我按照你的建议尝试了listen方法,但我得到了一堆错误。再次抱歉,我对 Flutter 很陌生
  • 很难解决“一堆错误”。您尝试了两种方法中的哪一种?无论错误如何,这种方法总体上是否有意义?如果是,您是如何实施该方法的,您究竟遇到了什么错误?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-23
  • 1970-01-01
  • 2013-04-22
  • 2017-07-10
  • 1970-01-01
  • 2013-08-17
  • 1970-01-01
相关资源
最近更新 更多