mcpField
F
flutter-change-notifier

flutter-change-notifier

github.com/evanca開発663195 回インストール3 週間前に更新
リポジトリ

flutter-change-notifier について

Flutter開発者向けに、ChangeNotifierとproviderを使った状態管理を説明するスキルです。モデルの構成、状態の提供と参照、不要なウィジェット再構築の抑制、通知のテストを扱います。

主な機能

  1. 01状態を非公開にし変更不可ビューを公開
  2. 02Providerでモデルを提供
  3. 03Consumerで状態を参照
  4. 04ウィジェット再構築の範囲を限定
  5. 05ChangeNotifierモデルをテスト

活用シーン

  1. 01Flutterウィジェット間でモデル状態を共有
  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 で状態管理を行うために、provider パッケージと ChangeNotifier を正しく使用する方法を説明します。


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 ではなく Consumer<CartModel>)。
  • child パラメーターを使用して、モデルに依存しないウィジェットを渡します。これらは一度だけビルドされ、再利用されます。
  • 再ビルドの範囲を最小限に抑えるため、Consumer ウィジェットはできるだけウィジェットツリーの深い位置に配置します。
HumongousWidget(
  child: AnotherMonstrousWidget(
    child: Consumer<CartModel>(
      builder: (context, cart, child) {
        return Text('Total price: ${cart.totalPrice}');
      },
    ),
  ),
)
Provider.of と listen: false

モデルの状態変化に反応する必要はなく、モデルのメソッドを呼び出すだけの場合は、Provider.of<T>(context, listen: false) を使用します。

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

4. 最適化のルール

  • モデルに依存するのが一部だけの場合、大きなウィジェットサブツリーを Consumer で囲まないでください。
  • ウィジェットツリーとプロバイダーの使い方を慎重に構成し、不要な再ビルドを避けます。
  • アクションを実行する一方で再ビルドが不要なコールバック(例: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);
});

参考資料

コメント