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

如何将自定义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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 08:43:11