flutter-change-notifier について
Flutter開発者向けに、ChangeNotifierとproviderを使った状態管理を説明するスキルです。モデルの構成、状態の提供と参照、不要なウィジェット再構築の抑制、通知のテストを扱います。
主な機能
- 01状態を非公開にし変更不可ビューを公開
- 02Providerでモデルを提供
- 03Consumerで状態を参照
- 04ウィジェット再構築の範囲を限定
- 05ChangeNotifierモデルをテスト
活用シーン
- 01Flutterウィジェット間でモデル状態を共有
- 02状態更新による再構築を削減
- 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);
});
参考資料
コメント
Markdown 対応