Flutter中如何为可复用Widget创建Provider类的独立实例?
购物车商品数量同步错误问题解决
问题描述
开发购物车页面时,每个商品卡片包含名称、图片、价格和带增减按钮的数量模块。当前遇到的问题是:调整某一商品的数量时,所有其他商品卡片的数量也会同步变化。
现有代码
UI代码
SizedBox( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ IconButton( icon: Icon( Icons.remove_circle_outline, color: context.color.primaryColor, ), onPressed: () { context.read<CartItemProvider>().dcrItem(); }, ), Text( "${context.watch<CartItemProvider>().noOfItem}", style: context.textTheme.displayLarge, ), IconButton( icon: Icon( Icons.add_circle, color: context.color.primaryColor, ), onPressed: () { context.read<CartItemProvider>().incItem(); }, ), ], ), )
Provider类代码
class CartItemProvider extends ChangeNotifier { int noOfItem = 1; void incItem() { noOfItem++; notifyListeners(); } void dcrItem() { if (noOfItem == 1) return; noOfItem--; notifyListeners(); } }
问题原因
当前的CartItemProvider只维护了一个全局的noOfItem变量,所有商品卡片都绑定这个变量的值。当任何一个商品的增减按钮触发修改时,这个全局变量会被更新,导致所有卡片的数量显示同步变化。
解决方案
需要为每个购物车商品单独维护数量,具体修改如下:
1. 创建购物车商品模型类
定义一个CartItem类,存储单个商品的信息和数量:
class CartItem { final String id; final String name; final double price; int quantity; CartItem({ required this.id, required this.name, required this.price, this.quantity = 1, }); }
2. 修改Provider类
让Provider维护一个购物车商品列表,实现针对单个商品的增减逻辑:
class CartItemProvider extends ChangeNotifier { final Map<String, CartItem> _items = {}; // 获取购物车商品列表 List<CartItem> get items => _items.values.toList(); // 增加指定商品的数量 void incrementItem(String productId) { if (_items.containsKey(productId)) { _items.update( productId, (existingItem) => CartItem( id: existingItem.id, name: existingItem.name, price: existingItem.price, quantity: existingItem.quantity + 1, ), ); notifyListeners(); } } // 减少指定商品的数量 void decrementItem(String productId) { if (_items.containsKey(productId)) { final existingItem = _items[productId]!; if (existingItem.quantity > 1) { _items.update( productId, (item) => CartItem( id: item.id, name: item.name, price: item.price, quantity: item.quantity - 1, ), ); } else { // 数量为1时可选择移除商品,也可以保持数量为1不操作 _items.remove(productId); } notifyListeners(); } } // 添加商品到购物车(已存在则增加数量) void addItem(String productId, String name, double price) { if (_items.containsKey(productId)) { incrementItem(productId); } else { _items.putIfAbsent( productId, () => CartItem(id: productId, name: name, price: price), ); notifyListeners(); } } }
3. 更新UI代码
每个商品卡片绑定对应商品的数量,调用针对该商品的增减方法:
ListView.builder( itemCount: context.watch<CartItemProvider>().items.length, itemBuilder: (context, index) { final cartItem = context.watch<CartItemProvider>().items[index]; return ListTile( title: Text(cartItem.name), subtitle: Text('\$${cartItem.price.toStringAsFixed(2)}'), trailing: Row( mainAxisSize: MainAxisSize.min, children: [ IconButton( icon: Icon( Icons.remove_circle_outline, color: context.color.primaryColor, ), onPressed: () { context.read<CartItemProvider>().decrementItem(cartItem.id); }, ), Text( "${cartItem.quantity}", style: context.textTheme.displayLarge, ), IconButton( icon: Icon( Icons.add_circle, color: context.color.primaryColor, ), onPressed: () { context.read<CartItemProvider>().incrementItem(cartItem.id); }, ), ], ), ); }, )
这样修改后,每个商品的数量都是独立维护的,调整某一商品数量时只会影响该商品的显示,不会同步修改其他商品的数量。
内容的提问来源于stack exchange,提问作者Shrijal Shrestha
相关产品推荐
相关产品推荐

