如何将自定义CoffeeItem类数据接入Flutter Provider购物车
解决用Provider将自定义CoffeeItem类接入购物车的问题
一、重构CartModel适配CoffeeItem类
原CartModel依赖数组索引和动态列表,需改为强类型的CoffeeItem列表,同时调整添加商品的逻辑为直接接收CoffeeItem对象:
class CartModel extends ChangeNotifier { // 替换为CoffeeItem类型的在售商品列表 final List<CoffeeItem> _shopItems = [ CoffeeItem( id: 1, title: "Brazil", image: "lib/assets/Brazil.png", description: "巴西风味咖啡豆,醇厚浓郁", image2: "lib/assets/Brazil.png", // 替换为对应详情页图片路径 productPrice: 15, quantity: 1, unit: "12oz" ), CoffeeItem( id: 2, title: "Colombia", image: "lib/assets/Colombia.png", description: "哥伦比亚咖啡豆,酸度明亮", image2: "lib/assets/Colombia.png", productPrice: 15, quantity: 1, unit: "12oz" ), // 补充其他咖啡商品实例 ]; // 购物车列表改为CoffeeItem强类型 final List<CoffeeItem> _cartItems = []; List<CoffeeItem> get cartItems => _cartItems; List<CoffeeItem> get shopItems => _shopItems; // 修改添加逻辑:直接接收CoffeeItem对象 void addItemToCart(CoffeeItem item) { _cartItems.add(item); notifyListeners(); } void removeItemFromCart(int index) { _cartItems.removeAt(index); notifyListeners(); } // 更新总价计算:直接访问CoffeeItem的productPrice属性 String calculateTotal() { double totalPrice = 0; for (var item in cartItems) { totalPrice += item.productPrice.toDouble(); } return totalPrice.toStringAsFixed(2); } }
二、修改购物车页面UI适配CoffeeItem对象
原代码通过数组索引访问属性,需改为直接调用CoffeeItem的成员变量:
Expanded( child: Padding( padding: const EdgeInsets.all(12.0), child: ListView.builder( itemCount: value.cartItems.length, padding: const EdgeInsets.all(12), itemBuilder: (context, index) { final CoffeeItem item = value.cartItems[index]; return Padding( padding: const EdgeInsets.all(12.0), child: Container( decoration: BoxDecoration( color: Colors.grey[200], borderRadius: BorderRadius.circular(8)), child: ListTile( leading: Image.asset( item.image, height: 36, ), title: Text( item.title, style: const TextStyle(fontSize: 18), ), subtitle: Text( '\$${item.productPrice.toStringAsFixed(2)}', style: const TextStyle(fontSize: 12), ), trailing: IconButton( icon: const Icon(Icons.cancel), onPressed: () => Provider.of<CartModel>(context, listen: false) .removeItemFromCart(index), ), ), ), ); }, ), ), )
总价计算区域无需修改,calculateTotal方法已适配新数据结构。
三、调整BeanScreen的添加购物车逻辑
原按钮错误传入ListView索引,需改为直接传入当前页面的widget.coffeeItem,同时移除多余的ListView嵌套:
class BeanScreen extends StatefulWidget { const BeanScreen(this.coffeeItem, {Key? key}) : super(key: key); final CoffeeItem coffeeItem; @override State<BeanScreen> createState() => _BeanScreen(); } class _BeanScreen extends State<BeanScreen> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Colors.blueGrey, title: const Text('Good Vibes Coffee Co.'), centerTitle: true, actions: [ InkWell( onTap: () { Navigator.push(context, MaterialPageRoute(builder: (context) => const CartPage())); }, child: Center( child: Badge( showBadge: true, animationType: BadgeAnimationType.fade, animationDuration: const Duration(milliseconds: 300), child: const Icon(Icons.shopping_bag_outlined), ), ), ), const SizedBox(width: 20.0) ], ), body: Column( children: [ Expanded( child: Column( children: [ Card( color: const Color.fromARGB(255, 255, 249, 193), child: Stack( alignment: Alignment.center, children: [ ClipRRect( borderRadius: const BorderRadius.all( Radius.circular(10), ), child: Image( image: AssetImage(widget.coffeeItem.image2), ), ), Center( child: Text( widget.coffeeItem.title, textAlign: TextAlign.center, style: const TextStyle( fontSize: 30, fontWeight: FontWeight.w900, ), ), ), ], ), ), Row( children: [ SizedBox( width: MediaQuery.of(context).size.width, child: Text(widget.coffeeItem.description, overflow: TextOverflow.visible, textAlign: TextAlign.center, style: const TextStyle(fontSize: 18))), ], ), const SizedBox(height: 50), Row( children: [ const SizedBox(width: 40), Consumer<CartModel>( builder: (context, value, child) { return ElevatedButton( style: ButtonStyle( backgroundColor: MaterialStateProperty.all( const Color.fromARGB( 255, 36, 194, 141))), onPressed: () { Provider.of<CartModel>(context, listen: false) .addItemToCart(widget.coffeeItem); // 添加成功提示 ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('商品已添加到购物车')), ); }, child: const Text('One-Time Purchase'), ); }, ), const SizedBox(width: 75), ElevatedButton( style: ButtonStyle( backgroundColor: MaterialStateProperty.all( const Color.fromARGB( 255, 36, 194, 141))), onPressed: () { Navigator.push( context, MaterialPageRoute( builder: ((context) => const Subscribe()), )); }, child: const Text('Subscribe')), ], ), const SizedBox(height: 20), Row( children: const [ SizedBox(width: 80), Text('\$15.00/12oz'), SizedBox(width: 120), Text('\$15.00/16oz') ], ), ], ), ), ], ), ); } }
内容的提问来源于stack exchange,提问作者KRAP
相关产品推荐
相关产品推荐

