mcpField
F
flutter-change-notifier

flutter-change-notifier

github.com/evanca开发663195 次安装3 周前更新
代码仓库

关于 flutter-change-notifier

面向 Flutter 开发的 ChangeNotifier 与 provider 状态管理技能,说明模型组织、状态提供和消费方式。还包含减少不必要重建及测试模型通知的指导。

主要功能

  1. 01封装私有状态并提供不可变视图
  2. 02通过 Provider 提供模型
  3. 03使用 Consumer 消费状态
  4. 04缩小组件重建范围
  5. 05编写 ChangeNotifier 单元测试

适用场景

  1. 01在 Flutter 应用中共享模型状态
  2. 02减少状态更新引发的组件重建
  3. 03验证模型状态变化与通知

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/evanca/flutter-ai-rules --skill flutter-change-notifier

安装后在 Claude Code 中输入/flutter-change-notifier确认已加载。

详细介绍

Flutter ChangeNotifier 技能

本技能介绍如何在 Flutter 中将 ChangeNotifier 与 provider 包搭配使用,以正确管理状态。


1. 模型

扩展 ChangeNotifier 以管理状态。将内部状态设为私有,并公开不可修改的视图。每次状态发生变化时,都调用 notifyListeners()。

class CartModel extends ChangeNotifier {
  final List<Item> _items = [];

  UnmodifiableListView<Item> get items => UnmodifiableListView(_items);

  void add(Item item) {
    _items.add(item);
    notifyListeners();
  }

  void removeAll() {
    _items.clear();
    notifyListeners();
  }
}
  • 在组件树中,将共享状态放在使用它的组件上方。
  • 切勿直接修改组件或调用组件上的方法来改变状态;应使用新数据重建组件。

2. 提供模型

ChangeNotifierProvider(
  create: (context) => CartModel(),
  child: MyApp(),
)
  • 当模型不再需要时,ChangeNotifierProvider 会自动释放它。
  • 需要提供多个模型时,使用 MultiProvider:
MultiProvider(
  providers: [
    ChangeNotifierProvider(create: (_) => CartModel()),
    ChangeNotifierProvider(create: (_) => UserModel()),
  ],
  child: MyApp(),
)

3. 使用状态

Consumer
Consumer<CartModel>(
  builder: (context, cart, child) => Stack(
    children: [
      if (child != null) child,
      Text('Total price: ${cart.totalPrice}'),
    ],
  ),
  child: const SomeExpensiveWidget(), // rebuilt only once
)
  • 始终指定泛型类型(Consumer<CartModel>,而不是 Consumer)。
  • 使用 child 参数传入不依赖模型的组件——它们只会构建一次,并在之后重复使用。
  • 将 Consumer 组件尽可能放在组件树的深处,以尽量缩小重建范围:
HumongousWidget(
  child: AnotherMonstrousWidget(
    child: Consumer<CartModel>(
      builder: (context, cart, child) {
        return Text('Total price: ${cart.totalPrice}');
      },
    ),
  ),
)
使用 listen: false 的 Provider.of

当只需要在模型上调用方法,而不需要响应状态变化时,使用 Provider.of<T>(context, listen: false):

Provider.of<CartModel>(context, listen: false).removeAll();

4. 优化规则

  • 如果只有一小部分依赖模型,不要用 Consumer 包裹大型组件子树。
  • 谨慎组织组件树和 provider 的用法,避免不必要地重建组件。
  • 在回调中(例如 onPressed)触发操作且不需要重建时,使用 listen: false。

5. 测试

为 ChangeNotifier 模型编写单元测试,以验证状态变化和通知:

test('adding item updates total', () {
  final cart = CartModel();
  var notified = false;
  cart.addListener(() => notified = true);

  cart.add(Item('Book'));

  expect(cart.items.length, 1);
  expect(notified, isTrue);
});

参考资料

评论

支持 Markdown