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

Flutter:修复ListView Builder中单个商品数量增减触发所有项同步变化的问题

问题分析与修复方案

我一眼就看出问题所在了:你的CartProvider里维护了一个全局的_quantity变量,所有商品的数量显示都绑定了这个值,而且增减操作也是直接修改这个全局变量,这就导致点击任何一个商品的增减按钮,所有商品的数量都会同步变化。另外,数据库更新数量的条件也写错了,这会导致更新逻辑出错。下面是具体的修复步骤和修改后的代码:

1. 修复CartProvider:移除全局quantity变量

每个商品的数量应该存储在对应的Cart对象和数据库里,CartProvider不需要维护单个商品的数量,只需要管理购物车总商品数和总价即可。修改后的CartProvider代码:

class CartProvider with ChangeNotifier {
  DBHelper dbHelper = DBHelper();
  int _counter = 0;
  int get counter => _counter;
  double _totalPrice = 0.0;
  double get totalPrice => _totalPrice;
  late Future<List<Cart>> _cart;
  Future<List<Cart>> get cart => _cart;

  Future<List<Cart>> getData() async {
    _cart = dbHelper.getCartList();
    return _cart;
  }

  void _setPrefsItems() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setInt('cart_items', _counter);
    prefs.setDouble('total_price', _totalPrice);
    notifyListeners();
  }

  void _getPrefsItems() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    _counter = prefs.getInt('cart_items') ?? 0;
    _totalPrice = prefs.getDouble('total_price') ?? 0;
  }

  void addCounter() {
    _counter++;
    _setPrefsItems();
    notifyListeners();
  }

  void removeCounter() {
    _counter--;
    _setPrefsItems();
    notifyListeners();
  }

  int getCounter() {
    _getPrefsItems();
    return _counter;
  }

  void addTotalPrice(double productPrice) {
    _totalPrice = _totalPrice + productPrice;
    _setPrefsItems();
    notifyListeners();
  }

  void removeTotalPrice(double productPrice) {
    _totalPrice = _totalPrice - productPrice;
    _setPrefsItems();
    notifyListeners();
  }

  double getTotalPrice() {
    _getPrefsItems();
    return _totalPrice;
  }

  // 新增方法:更新总价时重新计算,避免总价与实际商品总价不一致
  Future<void> refreshTotalPrice() async {
    List<Cart> cartList = await dbHelper.getCartList();
    _totalPrice = cartList.fold(0, (sum, item) => sum + (item.productPrice! * item.quantity!));
    _setPrefsItems();
  }
}

2. 修复DBHelper的updateQuantity方法

原来的where条件用了quantity = ?,这会更新所有quantity等于目标值的商品,完全错误。应该用商品的id来定位:

class DBHelper {
  // ... 其他代码保持不变 ...

  Future<int> updateQuantity(Cart cart) async {
    var dbClient = await database;
    // 修改where条件为id = ?,用cart.id定位具体商品
    return await dbClient!.update(
      'cart',
      cart.quantityMap(),
      where: "id = ?",
      whereArgs: [cart.id]
    );
  }

  // ... 其他代码保持不变 ...
}

3. 修复购物车页面的增减按钮逻辑和数量显示

  • 把PlusMinusButtons的text改成当前商品的quantity,而不是全局的cart.quantity
  • 修改增减按钮的逻辑,正确更新对应商品的数量,然后刷新购物车数据

修改后的购物车页面中ListView.builder的itemBuilder部分关键代码:

return Card(
  color: Colors.blueGrey.shade200,
  elevation: 5.0,
  child: Padding(
    padding: const EdgeInsets.all(4.0),
    child: Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      mainAxisSize: MainAxisSize.max,
      children: [
        // ... 商品图片、信息部分代码保持不变 ...
        PlusMinusButtons(
          addQuantity: () async {
            // 获取当前操作的商品
            Cart currentCartItem = snapshot.data![index];
            // 计算新数量和新总价
            int newQuantity = currentCartItem.quantity! + 1;
            int newProductPrice = currentCartItem.initialPrice! * newQuantity;
            // 更新数据库
            await dbHelper!.updateQuantity(
              Cart(
                id: currentCartItem.id,
                productId: currentCartItem.productId,
                productName: currentCartItem.productName,
                initialPrice: currentCartItem.initialPrice,
                productPrice: newProductPrice,
                quantity: newQuantity,
                unitTag: currentCartItem.unitTag,
                image: currentCartItem.image,
              )
            );
            // 更新Provider总价并刷新数据
            cart.addTotalPrice(currentCartItem.initialPrice!.toDouble());
            await cart.getData();
            cart.notifyListeners();
          },
          deleteQuantity: () async {
            Cart currentCartItem = snapshot.data![index];
            // 数量不能小于1
            if (currentCartItem.quantity! > 1) {
              int newQuantity = currentCartItem.quantity! - 1;
              int newProductPrice = currentCartItem.initialPrice! * newQuantity;
              await dbHelper!.updateQuantity(
                Cart(
                  id: currentCartItem.id,
                  productId: currentCartItem.productId,
                  productName: currentCartItem.productName,
                  initialPrice: currentCartItem.initialPrice,
                  productPrice: newProductPrice,
                  quantity: newQuantity,
                  unitTag: currentCartItem.unitTag,
                  image: currentCartItem.image,
                )
              );
              cart.removeTotalPrice(currentCartItem.initialPrice!.toDouble());
              await cart.getData();
              cart.notifyListeners();
            }
          },
          // 显示当前商品的数量,而非全局quantity
          text: snapshot.data![index].quantity.toString(),
        ),
        // ... 删除按钮代码保持不变 ...
      ],
    ),
  ),
);

4. 验证修复效果

现在点击单个商品的增减按钮,只会修改该商品的数量,价格也会正确更新,其他商品的数量不会受到影响。同时数据库的更新逻辑也能准确定位到对应的商品。

额外建议:在删除商品或者更新数量后,调用cart.refreshTotalPrice()来重新计算总价,避免因为异常操作导致总价和实际商品总价不一致的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 22:12:31