为什么使用_items.update创建一个新的Item而不是直接修改Item对象的内容

问题描述 投票:0回答:1

我是 Flutter 新手,正在学习 Udemy 上的课程。我有一个名为 Item 的模型,它具有

final
属性,如图所示:

class Item {
  final String id;
  final String title;
  final int quantity;
  final double price;

  Item({
    required this.id,
    required this.title,
    required this.quantity,
    required this.price,
  });
}

Item
由另一个类
Cart
使用,它在地图中存储
Item
的列表,并且它有一个
removeSingleItem
方法可以减少数量,如下所示:

class Cart with ChangeNotifier {
  Map<String, Item> _items = {};

void removeSingleItem(String productId) {
    if (!_items.containsKey(productId)) {
      return;
    }
    if (_items[productId]!.quantity > 1) {
      _items.update(
          productId,
          (existingCartItem) => Item(
                id: existingCartItem.id,
                price: existingCartItem.price,
                quantity: existingCartItem.quantity - 1,
                title: existingCartItem.title,
              ));
    } else {
      _items.remove(productId);
    }
    notifyListeners();
  }

我们可以看到购物车是一个提供商。

为什么我们要使用

Item
创建一个新的
_items.update
?而不是在将属性设置为非最终属性后直接修改 Item 对象的内容:

_items[产品Id]!.数量 -= 1;

这会导致状态管理出现问题吗?因为在演示应用程序中,即使我们不创建整个新的 Item 对象,订单屏幕(新的 Scaffold)似乎也会正确更新。

flutter dart provider
1个回答
3
投票

可变数据类最危险的事情是,它可以从代码的每个部分发生变化,而不仅仅是模型提供者。

这些是使数据不可变的一些方面:

  • 不可变数据类的构造函数为const,Flutter进一步优化了const对象;
  • 框架可以有效地检测状态变化,因为唯一需要的比较是检查对象引用是否已更改;
  • 处理数据变得更安全,因为在不可预测的地方不会产生副作用或突变;

这就是为什么一堆类具有

copyWith
方法来仅改变一个属性,但它返回一个新的对象实例。

因此,使

Item
不可变并创建一个
copyWith
方法,如以下代码片段所示:

class Item {
  final String id;
  final double price;
  final double quantity;
  final String title;
  const Item({
    required this.id,
    required this.price,
    required this.quantity,
    required this.title,
  });

  Item copyWith({
    String? id,
    double? price,
    double? quantity,
    String? title,
  }) {
    return Item(
      id: id ?? this.id,
      price: price ?? this.price,
      quantity: quantity ?? this.quantity,
      title: title ?? this.title,
    );
  }
}

通过这种方式从现有实例创建新实例要容易得多:

  _items.update(
      productId,
      (existingCartItem) => existingCartItem.copyWith(
            quantity: existingCartItem.quantity - 1,
          ));

© www.soinside.com 2019 - 2024. All rights reserved.