
claude-skills 仓库 flutter-expert 技能实战指南Flutter 3 跨平台应用的 Riverpod/Bloc 状态管理、GoRouter 导航与性能优化【免费下载链接】claude-skills67 Specialized Skills for Full-Stack Developers. Transform Claude Code into your expert pair programmer.项目地址: https://gitcode.com/GitHub_Trending/claud/claude-skills导读本文以 claude-skills 仓库中的 flutter-expert 技能 为骨架系统讲解在 Flutter 3 / Dart 环境下开发高性能跨平台应用的核心工程实践从项目搭建、状态管理Riverpod / Bloc选型到 GoRouter 导航配置、可复用 Widget 设计再到 DevTools 性能剖析与测试验证的完整闭环。读完本文你将掌握一套可落地的 Flutter 开发工作流包括flutter analyze/flutter test/flutter run --profile的正确使用节奏以及const优化、select()选择性重建、compute()隔离重计算等关键性能手段。一、技能定位什么时候该用 flutter-expertclaude-skills 是一套面向全栈开发者的 Agent Skills 集合flutter-expert 是其中面向移动前端的专项技能。从 SKILL.md 的 frontmatter 可以看到它的元数据定义name: flutter-expert description: Use when building cross-platform applications with Flutter 3 and Dart. Invoke for widget development, Riverpod/Bloc state management, GoRouter navigation, platform-specific implementations, performance optimization. metadata: version: 1.1.0 domain: frontend triggers: Flutter, Dart, widget, Riverpod, Bloc, GoRouter, cross-platform role: specialist scope: implementation output-format: code related-skills: react-native-expert, test-master, fullstack-guardian这套 frontmatter 遵循项目在 CLAUDE.md 中定义的 Agent Skills 规范description只声明“能力 触发条件”不写过程步骤避免 Agent 因看到简短描述而跳过正文triggers提供可检索关键词related-skills声明与 react-native-expert、test-master、fullstack-guardian 的协作关系。在 SKILLS_GUIDE.md 的技能路由表中移动端Dart任务明确指向 Flutter Expert并给出了“Flutter Expert / React Native Expert API Designer DevOps Engineer”的组合用法。适用场景场景说明构建跨平台应用一套 Dart 代码同时产出 iOS / Android / Web 等目标状态管理实现RiverpodProvider/Notifier或 Bloc/Cubit 选型与落地GoRouter 导航路由表、嵌套路由、深链接、鉴权守卫自定义 Widget 与动画可复用组件、const 优化、Sliver 布局性能优化DevTools Profile、jank 消除、重建抑制平台差异化实现平台特定代码与行为适配二、核心工作流从搭建到优化的五步闭环SKILL.md 定义了 flutter-expert 的核心工作流每一步都绑定了可验证的 CLI 命令形成“实现 → 静态检查 → 测试 → 覆盖 → 剖析”的闭环。Step 1 — Setup脚手架与依赖使用flutter create脚手架初始化项目在pubspec.yaml中声明依赖后执行flutter pub get拉取配置路由GoRouter与入口ProviderScope/BlocProvider。Step 2 — State定义状态并跑静态检查定义 Riverpod Provider 或 Bloc/Cubit 之后必须运行flutter analyze工作流要求如果flutter analyze报错必须修复全部 lint 与警告后再继续并重新运行直到干净。这一步把类型问题、未解析导入、缺失的const在编译前拦截下来。Step 3 — Widgets构建组件并跑测试构建可复用、const 优化的组件后每个功能完成后运行flutter test如果测试失败用 Flutter DevTools 检查 widget 树 → 修复失败断言 → 重新运行。Step 4 — Test补充覆盖率flutter test --coverage如果覆盖率下降或测试失败定位未覆盖分支补充针对性测试合并前重新运行。Step 5 — Optimize剖析与去 jankflutter run --profile如果卡顿jank依旧在 Performance overlay 中检查重建次数隔离耗时的build()调用应用const或把状态下沉到更靠近消费者的位置。三、Riverpod 状态管理Provider 体系与 Notifier 模式参考文档 riverpod-state.md 完整覆盖了 Riverpod 2.x 的 Provider 类型体系。三类基础 Providerimport package:flutter_riverpod/flutter_riverpod.dart; // 简单可变状态 final counterProvider StateProviderint((ref) 0); // 异步状态API 调用 final usersProvider FutureProviderListUser((ref) async { final api ref.read(apiProvider); return api.getUsers(); }); // 流状态实时数据 final messagesProvider StreamProviderListMessage((ref) { return ref.read(chatServiceProvider).messagesStream; });Riverpod 2.0 Notifier 模式Codegenriverpod class TodoList extends _$TodoList { override ListTodo build() []; void add(Todo todo) { state [...state, todo]; // 不可变更新始终产生新实例 } void toggle(String id) { state [ for (final todo in state) if (todo.id id) todo.copyWith(completed: !todo.completed) else todo, ]; } void remove(String id) { state state.where((t) t.id ! id).toList(); } }异步场景使用AsyncNotifier配合AsyncValue.guard统一处理 loading / data / errorriverpod class UserProfile extends _$UserProfile { override FutureUser build() async { return ref.read(apiProvider).getCurrentUser(); } Futurevoid updateName(String name) async { state const AsyncValue.loading(); state await AsyncValue.guard(() async { final updated await ref.read(apiProvider).updateUser(name: name); return updated; }); } }在 Widget 中消费状态推荐ConsumerWidgetref.watch并通过select()做选择性订阅// 推荐写法TodoScreen class TodoScreen extends ConsumerWidget { const TodoScreen({super.key}); override Widget build(BuildContext context, WidgetRef ref) { final todos ref.watch(todoListProvider); return ListView.builder( itemCount: todos.length, itemBuilder: (context, index) { final todo todos[index]; return ListTile( title: Text(todo.title), leading: Checkbox( value: todo.completed, onChanged: (_) ref.read(todoListProvider.notifier).toggle(todo.id), ), ); }, ); } } // 选择性重建只有 avatarUrl 变化时才重建 class UserAvatar extends ConsumerWidget { const UserAvatar({super.key}); override Widget build(BuildContext context, WidgetRef ref) { final avatarUrl ref.watch(userProvider.select((u) u?.avatarUrl)); return CircleAvatar( backgroundImage: avatarUrl ! null ? NetworkImage(avatarUrl) : null, ); } }异步状态的三态渲染用.when(...)final userAsync ref.watch(userProfileProvider); return userAsync.when( data: (user) Text(user.name), loading: () const CircularProgressIndicator(), error: (err, stack) Text(Error: $err), );Provider 速查表Provider适用场景Provider计算/派生值StateProvider简单可变状态FutureProvider一次性异步操作StreamProvider实时数据流NotifierProvider带方法的复杂状态AsyncNotifierProvider带方法的异步状态四、Bloc 状态管理事件驱动与 Cubit 简配参考文档 bloc-state.md 给出了 Bloc 的适用边界简单可变状态用 Riverpod事件驱动的工作流、表单/认证/向导、功能模块用 Bloc。核心概念概念描述Event用户/系统输入State不可变 UI 状态BlocEvent → State 映射器Cubit仅状态、无事件最小 Bloc 实现sealed class CounterEvent {} final class CounterIncremented extends CounterEvent {} final class CounterDecremented extends CounterEvent {} class CounterState { final int value; const CounterState({required this.value}); CounterState copyWith({int? value}) { return CounterState(value: value ?? this.value); } } class CounterBloc extends BlocCounterEvent, CounterState { CounterBloc() : super(const CounterState(value: 0)) { onCounterIncremented((event, emit) { emit(state.copyWith(value: state.value 1)); }); onCounterDecremented((event, emit) { emit(state.copyWith(value: state.value - 1)); }); } }Cubit简单逻辑的推荐方案class CounterCubit extends Cubitint { CounterCubit() : super(0); void increment() emit(state 1); void decrement() emit(state - 1); }注入与消费注入使用BlocProvider/MultiBlocProvider消费端有四种形态Widget用途BlocBuilder按状态重建 UI可用buildWhen精细控制BlocListener执行一次性副作用SnackBar、导航用listenWhen过滤BlocConsumerBuilder Listener 组合BlocProvider/MultiBlocProvider依赖注入典型写法含异步 API 调用与路由守卫// 异步加载 onUserRequested((event, emit) async { emit(const UserState.loading()); try { final user await repository.fetchUser(); emit(UserState.success(user)); } catch (e) { emit(UserState.failure(e.toString())); } }); // 认证守卫Bloc GoRouter redirect: (context, state) { final authState context.readAuthBloc().state; if (authState is Unauthenticated) { return /login; } return null; }测试 BlocblocTestCounterBloc, CounterState( emits incremented value, build: () CounterBloc(), act: (bloc) bloc.add(CounterIncremented()), expect: () [const CounterState(value: 1)], );Bloc 铁律状态不可变、Bloc 小而聚焦、一个功能一个 Bloc、能上 Cubit 就上 Cubit、全部测试Bloc 内禁止 UI 逻辑、禁止使用context、禁止可变状态、禁止巨型“上帝 Bloc”。五、GoRouter 导航路由表、嵌套路由与深链参考文档 gorouter-navigation.md 从MaterialApp.router接入讲起。基础配置与重定向import package:go_router/go_router.dart; final goRouter GoRouter( initialLocation: /, redirect: (context, state) { final isLoggedIn /* 认证检查 */; if (!isLoggedIn !state.matchedLocation.startsWith(/auth)) { return /auth/login; } return null; }, routes: [ GoRoute( path: /, builder: (context, state) const HomeScreen(), routes: [ GoRoute( path: details/:id, // 路径参数 builder: (context, state) { final id state.pathParameters[id]!; return DetailsScreen(id: id); }, ), ], ), GoRoute( path: /auth/login, builder: (context, state) const LoginScreen(), ), ], ); class MyApp extends StatelessWidget { const MyApp({super.key}); override Widget build(BuildContext context) { return MaterialApp.router( routerConfig: goRouter, theme: AppTheme.light, darkTheme: AppTheme.dark, ); } }导航方法与参数传递context.go(/details/123); // 替换历史栈 context.push(/details/123); // 压栈 context.pop(); // 返回 context.pushReplacement(/home); // 替换当前路由 context.push(/details/123, extra: {title: Item}); // 携带 extra 数据 // 目标页读取 extra final extra GoRouterState.of(context).extra as MapString, dynamic?;ShellRoute底部导航持久 UIShellRoute( builder: (context, state, child) ScaffoldWithNavBar(child: child), routes: [ GoRoute(path: /home, builder: (_, __) const HomeScreen()), GoRoute(path: /profile, builder: (_, __) const ProfileScreen()), GoRoute(path: /settings, builder: (_, __) const SettingsScreen()), ], )查询参数GoRoute( path: /search, builder: (context, state) { final query state.uri.queryParameters[q] ?? ; final page int.tryParse(state.uri.queryParameters[page] ?? 1) ?? 1; return SearchScreen(query: query, page: page); }, ) // context.go(/search?qflutterpage2);导航速查表方法/语法行为context.go()导航并替换栈context.push()导航并压栈context.pop()返回context.pushReplacement()替换当前页:param路径参数?keyvalue查询参数六、Widget 模式const 优化、响应式布局与 Sliver参考文档 widget-patterns.md 提供可直接复用的组件范式。const 优化组件class OptimizedCard extends StatelessWidget { final String title; final VoidCallback onTap; const OptimizedCard({super.key, required this.title, required this.onTap}); override Widget build(BuildContext context) { return Card( child: InkWell( onTap: onTap, child: Padding( padding: const EdgeInsets.all(16), child: Text(title, style: Theme.of(context).textTheme.titleMedium), ), ), ); } }响应式布局LayoutBuilder 断点class ResponsiveLayout extends StatelessWidget { final Widget mobile; final Widget? tablet; final Widget desktop; const ResponsiveLayout({ super.key, required this.mobile, this.tablet, required this.desktop, }); override Widget build(BuildContext context) { return LayoutBuilder( builder: (context, constraints) { if (constraints.maxWidth 1100) return desktop; if (constraints.maxWidth 650) return tablet ?? mobile; return mobile; }, ); } }flutter_hooks 自定义 Hookclass CounterWidget extends HookWidget { override Widget build(BuildContext context) { final counter useState(0); final controller useTextEditingController(); useEffect(() { // 初始化 return () { // 清理 }; }, []); return Column( children: [ Text(Count: ${counter.value}), ElevatedButton( onPressed: () counter.value, child: const Text(Increment), ), ], ); } }Sliver 滚动模式CustomScrollView( slivers: [ SliverAppBar( expandedHeight: 200, pinned: true, flexibleSpace: FlexibleSpaceBar( title: const Text(Title), background: Image.network(imageUrl, fit: BoxFit.cover), ), ), SliverList( delegate: SliverChildBuilderDelegate( (context, index) ListTile(title: Text(Item $index)), childCount: 100, ), ), ], )关键优化模式速查模式实现const widgets静态 Widget 一律加constkeys列表项使用Keyselectref.watch(provider.select(...))精确订阅RepaintBoundary隔离昂贵重绘ListView.builder列表懒加载const constructors尽可能使用常量构造七、项目结构Feature-Based 分层架构参考文档 project-structure.md 给出了适合中小型团队的按功能feature组织的目录结构并配套了完整的 pubspec 依赖清单。目录结构lib/ ├── main.dart ├── app.dart ├── core/ │ ├── constants/ # colors.dart, strings.dart │ ├── theme/ # app_theme.dart, text_styles.dart │ ├── utils/ # extensions.dart, validators.dart │ └── errors/ # failures.dart ├── features/ │ ├── auth/ │ │ ├── data/ # repositories/, datasources/ │ │ ├── domain/ # entities/, usecases/ │ │ ├── presentation/ # screens/, widgets/ │ │ └── providers/ # auth_provider.dart │ └── home/ # 同 auth 分层 ├── shared/ │ ├── widgets/ # buttons/, inputs/, cards/ │ ├── services/ # api_service.dart, storage_service.dart │ └── models/ # user.dart └── routes/ └── app_router.dart各层职责层职责data/API 调用、本地存储、DTOdomain/业务逻辑、实体、用例presentation/UI 页面与组件providers/该功能的 Riverpod Provider入口与 App 组装// main.dart void main() async { WidgetsFlutterBinding.ensureInitialized(); await Hive.initFlutter(); runApp(const ProviderScope(child: MyApp())); } // app.dart class MyApp extends ConsumerWidget { const MyApp({super.key}); override Widget build(BuildContext context, WidgetRef ref) { final router ref.watch(routerProvider); return MaterialApp.router( routerConfig: router, theme: AppTheme.light, darkTheme: AppTheme.dark, themeMode: ThemeMode.system, ); } }推荐依赖pubspec.yamldependencies: flutter: sdk: flutter # 状态管理 flutter_riverpod: ^2.5.0 riverpod_annotation: ^2.3.0 # 导航 go_router: ^14.0.0 # 网络 dio: ^5.4.0 # 代码生成 freezed_annotation: ^2.4.0 json_annotation: ^4.8.0 # 本地存储 shared_preferences: ^2.2.0 hive_flutter: ^1.1.0 dev_dependencies: flutter_test: sdk: flutter build_runner: ^2.4.0 riverpod_generator: ^2.4.0 freezed: ^2.5.0 json_serializable: ^6.8.0 flutter_lints: ^4.0.0依赖版本以当前项目参考文档记录为准实际接入时应以 pub.dev 上与你所用 Flutter SDK 兼容的最新版本为准。八、性能优化剖析命令、重建抑制与隔离计算参考文档 performance.md 是排查 jank 与内存问题的实操手册。剖析命令# Profile 模式运行性能数据才有效 flutter run --profile # 静态分析 flutter analyze # DevTools flutter pub global activate devtools flutter pub global run devtools注意性能剖析必须在--profile或--release模式下进行debug 模式的 JIT 开销会让数据失真。三类高频优化1. const 抑制重建// ❌ 每次 build 都创建新对象 Widget build(BuildContext context) { return Container( padding: EdgeInsets.all(16), child: Text(Hello), ); } // ✅ const 让对象可复用 Widget build(BuildContext context) { return Container( padding: const EdgeInsets.all(16), child: const Text(Hello), ); }2. 选择性订阅// ❌ user 任何字段变化都会重建 final user ref.watch(userProvider); return Text(user.name); // ✅ 只有 name 变化才重建 final name ref.watch(userProvider.select((u) u.name)); return Text(name);3. 重计算进隔离区// ❌ 阻塞 UI 线程 final result heavyComputation(data); // ✅ 运行在独立 isolate final result await compute(heavyComputation, data);图片与重绘优化// 网络图片缓存cached_network_image CachedNetworkImage( imageUrl: url, placeholder: (_, __) const CircularProgressIndicator(), errorWidget: (_, __, ___) const Icon(Icons.error), ); // 内存中按需缩放 Image.network(url, cacheWidth: 200, cacheHeight: 200); // 隔离昂贵动画的重绘 RepaintBoundary(child: ComplexAnimatedWidget());性能检查清单检查项解决方案不必要的重建加const、用select()大列表用ListView.builder图片加载用cached_network_image重计算用compute()动画 jank用RepaintBoundary内存泄漏及时 dispose 控制器DevTools 关键指标帧渲染时间60fps 需小于 16msWidget 重建数最小化非必要重建内存使用留意泄漏CPU Profiler定位瓶颈函数。九、常见故障排查速查表SKILL.md 将高频失败场景、根因与恢复动作整理成表直接指导 Agent 与开发者快速定位症状可能原因恢复方法flutter analyze报错未解析的导入、缺失const、类型不匹配修复标红行缺导入先flutter pub getWidget 测试断言失败Widget 树不匹配或异步状态未安定状态变更后用tester.pumpAndSettle()核对 finder 选择器加包后构建失败依赖版本不兼容flutter pub upgrade --major-versions查 pub.dev 兼容性Jank / 掉帧昂贵的build()、未缓存 Widget、主线程重负载用RepaintBoundary、把重活交给compute()、补const热重载不生效状态仍握在StateNotifier中未重置用热重启终端按R重置整个应用状态十、输出规范Agent 交付 Flutter 代码的标准清单SKILL.md 要求实现 Flutter 功能时交付内容必须包含四件套正确使用const的 Widget 代码Provider / Bloc 定义按需的路由配置测试文件结构。同时遵守 MUST DO / MUST NOT DO 约束必须做尽量使用const构造器列表项实现合理 keys状态管理用Consumer/ConsumerWidget而非StatefulWidget遵循 Material/Cupertino 设计规范用 DevTools 剖析并修复 jank用flutter_test编写 Widget 测试。禁止做在build()方法内构建 Widget直接修改 state必须创建新实例用setState管理应用级状态跳过静态 Widget 的const忽略平台特定行为用重计算阻塞 UI 线程改用compute()。十一、如何在本仓库中深入阅读flutter-expert 技能采用渐进式披露Progressive Disclosure架构SKILL.md 作为 Tier 1 提供路由表Tier 2 的参考文档按需加载。你可以直接阅读以下文件继续深挖技能主文档skills/flutter-expert/SKILL.mdRiverpod 状态管理skills/flutter-expert/references/riverpod-state.mdBloc 状态管理skills/flutter-expert/references/bloc-state.mdGoRouter 导航skills/flutter-expert/references/gorouter-navigation.mdWidget 模式skills/flutter-expert/references/widget-patterns.md项目结构skills/flutter-expert/references/project-structure.md性能优化skills/flutter-expert/references/performance.md技能协作方面flutter-expert 与 test-master测试策略、fullstack-guardian全栈落地、react-native-expert移动端替代方案互为补充具体组合方式见 SKILLS_GUIDE.md技能元数据与参考文件的编写规范见 CLAUDE.md。需要注意的是仓库采用只读模式本文仅说明阅读与本地应用的路径不涉及对仓库内容的修改。结合本文的闭环工作流一个典型的实践路径是按 feature 分层搭建项目 → 用 Riverpod/Bloc 管理状态并通过flutter analyze守门 → 用 GoRouter 配置导航与鉴权 → 组件遵循 const 与响应式模式 → 每功能flutter test→ 上线前flutter run --profile DevTools 消除 jank。这套方法论既适用于 Agent 协作场景也完全适用于人工开发的日常迭代。【免费下载链接】claude-skills67 Specialized Skills for Full-Stack Developers. Transform Claude Code into your expert pair programmer.项目地址: https://gitcode.com/GitHub_Trending/claud/claude-skills创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考