npx claudepluginhub caphtech/claude-marketplace --plugin mobile-pluginWant just this skill?
Then install: npx claudepluginhub u/[userId]/[slug]
Flutter Widgetの肥大化を、責務分離・共通化・Riverpod境界の整理でリファクタリングする。build()が長い、Widgetを分割したい、Riverpodのwatch/read/listen/select境界を見直したい、共通化したい、Flutter UIを整理したい時に使用。
This skill uses the workspace's default tool permissions.
references/decomposition-checklist.mdreferences/riverpod-boundaries.mdFlutter Widget Splitting
Flutter + Riverpod の Widget 分割と共通化を、実装までつながる形で支援する。
対象
- Flutter UI
flutter_riverpod/riverpod- 巨大な
build()/ConsumerWidget/ 画面単位のリファクタ - helper method ベースの UI を Widget 化したいケース
開始時に確認する
- 対象ファイル、画面、Widget を特定する
- 状態管理が Flutter ローカル state か Riverpod かを確認する
- 変更目的を1行で固定する。可読性、再利用、再ビルド境界、テスト性のどれを優先するか明確にする
- 分割位置の判定に迷う場合は references/decomposition-checklist.md を読む
- Riverpod の
watch/read/listen/select境界に迷う場合は references/riverpod-boundaries.md を読む
基本原則
- 行数ではなく、責務と変化の境界で分割する
- 再利用や再ビルド最適化が欲しい UI は helper method ではなく Widget にする
ref.watchは値を使う最小の Widget まで下ろす- 共有された業務状態は Provider に置き、一時 UI 状態はローカルに置く
- 副作用は
ref.listen、書き込みはイベントハンドラ内のref.readに寄せる const化と builder 系 Widget を優先する
ワークフロー
Step 1: build() の中身を4種類に色分けする
- 純 UI:
Text,Padding,Row,Card, 装飾 - 共有状態:
ref.watch(...)や ViewModel / Notifier の状態 - 一時 UI 状態: 展開、タブ、入力途中、controller、animation
- 副作用: snackbar, dialog, navigation, submit
Step 2: 状態の置き場を固定する
- 共有された業務状態:
Provider/Notifier/AsyncNotifier - 一時 UI 状態:
StatefulWidget/ hooks / controller - 副作用:
ref.listen - 書き込み:
ref.read(provider.notifier).method()
一時 UI 状態を Provider に入れたくなったら、まず route をまたいで共有すべきかを疑う。
TextEditingController やフォーム入力途中の値は原則ローカルに置く。
Step 3: 分割レイヤーを決める
以下の4層で切る。
Page:Scaffoldと画面全体の骨組みSection: 意味のある塊。header, list, action bar などComponent: 再利用できる部品。card, row, tile, button groupLeaf:constにしやすい最小の表示部品
Step 4: Riverpod 境界を切る
- 画面ルートで大きく
watchしない - provider を読む Widget は
ConsumerWidget/Consumerとして局所化する - 一部プロパティしか使わないなら
select - 非同期 provider の一部だけ必要なら
selectAsync ref.listenは effect 専用 Widget か画面境界に置く
Step 5: 下から順に抽出する
constにできる純 UI をStatelessWidget化する- provider を読む Section を
ConsumerWidget化する - 一時 UI 状態を持つ箇所だけ
StatefulWidgetに閉じ込める - helper method を、責務のある Widget に置き換える
build()内の整形や条件分岐が重い場合は Provider / Notifier 側へ移す
Step 6: 共通化は2段階で行う
- まずは画面専用の private widget に切り出す
- 2画面目や3箇所目で再利用が見えたら shared component に昇格する
最初から CommonCard や BaseTile のような抽象度の高い共通Widgetを作らない。
変わる軸が見えた後で API を作る。
Step 7: 仕上げに確認する
Pageが provider を読みすぎていないかwatchが最小境界にあるかlistenとreadの役割が分かれているかfamily/ 引数付き provider が不要に保持されていないかconstと builder 系を落としていないかflutter analyze/flutter testがあれば回す
典型パターン
helper method を Widget にする
class ProfilePage extends StatelessWidget {
const ProfilePage({super.key});
@override
Widget build(BuildContext context) {
return const Column(
children: [
ProfileHeader(),
ProfileStats(),
],
);
}
}
provider 読み取りを Section に閉じ込める
class ProfileStats extends ConsumerWidget {
const ProfileStats({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final followers = ref.watch(profileProvider.select((it) => it.followers));
final posts = ref.watch(profileProvider.select((it) => it.posts));
return StatsRow(followers: followers, posts: posts);
}
}
副作用は listen、更新は read
class SaveProfileButton extends ConsumerWidget {
const SaveProfileButton({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
ref.listen(saveProfileProvider, (_, next) {
next.whenOrNull(
data: (_) => ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Saved')),
),
);
});
return FilledButton(
onPressed: () => ref.read(saveProfileProvider.notifier).save(),
child: const Text('Save'),
);
}
}
禁止寄りのパターン
- 画面ルートで巨大な
ConsumerWidgetを作り、複数 provider をまとめてwatchする readで再ビルドを無理に避ける- controller やフォーム途中値を Provider に載せる
- 副作用を
build()やwatchと混ぜる - 再利用したい UI を
_buildHeader()のような method のまま維持する - 早すぎる汎用化で抽象度だけ高い共通Widgetを作る
出力
最終的に以下を返す。
- どこで分割するか
- 各 Widget の責務
- Provider / Widget の状態所有
watch/read/listen/selectの配置- 必要ならリファクタ後のコード差分
Similar Skills
Expert guidance for Next.js Cache Components and Partial Prerendering (PPR). **PROACTIVE ACTIVATION**: Use this skill automatically when working in Next.js projects that have `cacheComponents: true` in their next.config.ts/next.config.js. When this config is detected, proactively apply Cache Components patterns and best practices to all React Server Component implementations. **DETECTION**: At the start of a session in a Next.js project, check for `cacheComponents: true` in next.config. If enabled, this skill's patterns should guide all component authoring, data fetching, and caching decisions. **USE CASES**: Implementing 'use cache' directive, configuring cache lifetimes with cacheLife(), tagging cached data with cacheTag(), invalidating caches with updateTag()/revalidateTag(), optimizing static vs dynamic content boundaries, debugging cache issues, and reviewing Cache Component implementations.
Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.