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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 20:34:57