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
相关产品推荐
相关产品推荐

