Reviews Flutter/Dart code across state management (BLoC, Riverpod, Provider, GetX, MobX, Signals), Widget practices, Dart idioms, performance, accessibility, and architecture.
How this skill is triggered — by the user, by Claude, or both
Slash command
/everything-claude-code:flutter-dart-code-reviewThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
全面的、库无关的 Flutter/Dart 应用审查清单。无论使用哪种状态管理方案、路由库或 DI 框架,这些原则都适用。
全面的、库无关的 Flutter/Dart 应用审查清单。无论使用哪种状态管理方案、路由库或 DI 框架,这些原则都适用。
pubspec.yaml 干净——没有未使用的依赖,版本适当固定analysis_options.yaml 包含严格的分析器设置print() 语句——使用 dart:developer log() 或日志包.g.dart、.freezed.dart、.gr.dart)是最新的或在 .gitignore 中dynamic——启用 strict-casts、strict-inference、strict-raw-types!(bang 操作符)而非适当的空值检查或 Dart 3 模式匹配(if (value case var v?))this.field 而非局部变量提升catch (e) 没有 on 子句;始终指定异常类型Error:Error 子类型表示 bug,不应被捕获async:标记为 async 但从不 await 的函数——不必要的开销late 过度使用:在可空或构造函数初始化更安全的地方使用 late;将错误推迟到运行时StringBuffer 而非 + 进行迭代式字符串构建const 上下文中的可变状态:const 构造函数类中的字段不应可变Future 返回值:使用 await 或显式调用 unawaited() 表明意图final 时用了 var:局部变量优先用 final,编译时常量用 constpackage: 导入保持一致性List/Mapif-case 而非冗长的 is 检查和手动类型转换(String, int) 而非一次性 DTOprint():使用 dart:developer log() 或项目的日志包;print() 没有日志级别且无法过滤build() 方法超过约 80-100 行_build*() 辅助方法被提取为单独的 Widget 类(启用元素复用、const 传播和框架优化)const 构造函数——防止不必要的重建const 字面量(const []、const {})constValueKey 在重排序时保留状态GlobalKey——仅在真正需要跨树访问状态时使用build() 中避免 UniqueKey——它会强制每帧重建ObjectKeyTheme.of(context).colorScheme——没有硬编码的 Colors.red 或十六进制值Theme.of(context).textTheme——没有带原始字体大小的内联 TextStylebuild() 中没有网络调用、文件 I/O 或繁重计算build() 中没有 Future.then() 或 async 工作build() 中没有创建订阅(.listen())setState() 局限于最小的子树这些原则适用于所有 Flutter 状态管理方案(BLoC、Riverpod、Provider、GetX、MobX、Signals、ValueNotifier 等)。
ref.watch 依赖提供者是预期的——仅标记循环或过度纠缠的链copyWith() 或构造函数创建新实例,从不原地修改== 和 hashCode(所有字段包含在比较中)Equatable、freezed、Dart 记录或其他List/Map 暴露@action、Signals 中的 .value、GetX 中的 .obs)——直接字段修改绕过变更跟踪ReactionDisposer、Signals 中的 effect 清理)AsyncValue)——而非布尔标志(isLoading、isError、hasData)// 错误——布尔标志组合允许不可能的状态
class UserState {
bool isLoading = false;
bool hasError = false; // isLoading && hasError 是可表示的!
User? user;
}
// 正确(不可变方式)——密封类型使不可能的状态不可表示
sealed class UserState {}
class UserInitial extends UserState {}
class UserLoading extends UserState {}
class UserLoaded extends UserState {
final User user;
const UserLoaded(this.user);
}
class UserError extends UserState {
final String message;
const UserError(this.message);
}
// 正确(响应式方式)——可观察枚举 + 数据,通过响应式 API 变更
// enum UserStatus { initial, loading, loaded, error }
// 使用你的方案的可观察/信号来分别包装状态和数据
const Widget 阻止重建传播穿透树.listen())在 dispose() / close() 中取消.listen())setState 前检查 mountedawait 后不使用 BuildContext 而不检查 context.mounted(Flutter 3.7+)——过期上下文导致崩溃BuildContext 永远不存储在单例、状态管理器或静态字段中setState、ValueNotifier)setState() 不在根 Widget 级别调用——局部化状态变更const Widget 阻止重建传播RepaintBoundaryAnimatedBuilder 的 child 参数用于与动画无关的子树build() 中没有排序、过滤或映射大集合——在状态管理层计算build() 中没有正则编译MediaQuery.of(context) 使用特定的方法(如 MediaQuery.sizeOf(context))Image.asset 使用 cacheWidth/cacheHeight 以显示尺寸解码ListView.builder / GridView.builder 而非 ListView(children: [...])(小型静态列表使用具体构造函数没问题)deferred as)Opacity Widget——使用 AnimatedOpacity 或 FadeTransitionoperator ==——改用 const 构造函数IntrinsicHeight、IntrinsicWidth)谨慎使用(额外布局遍历)pumpWidget 和 pump 进行异步操作find.byType、find.text、find.byKeypumpAndSettle 或显式 pump(Duration)Semantics Widget 在自动标签不足处提供屏幕阅读器标签ExcludeSemanticsMergeSemantics 将相关 Widget 合并为单个可访问元素semanticLabel 属性onPressed 回调——每个按钮执行操作或被禁用SafeArea Widget 处理状态栏和安全区域AndroidManifest.xml 和 Info.plist 中声明LayoutBuilder 或 MediaQuery 进行响应式布局Flexible、Expanded、FittedBox--dart-define、排除在 VCS 外的 .env 文件或编译时配置.gitignore^1.2.3)——允许兼容更新flutter pub outdated 跟踪过时依赖pubspec.yaml 中没有依赖覆盖——仅用于临时修复并附注释/issue 链接package:other/src/internal.dart(破坏 Dart 包封装)path: ../../ 相对字符串analysis_options.yamlNavigator.push 和声明式路由器Map<String, dynamic> 或 Object? 类型转换FlutterError.onError 捕获框架错误(build、layout、paint)PlatformDispatcher.instance.onError 处理 Flutter 未捕获的异步错误ErrorWidget.builder 用于发布模式(用户友好而非红色屏幕)runApp 周围的全局错误捕获包装器(如 runZonedGuarded、Sentry/Crashlytics 包装器)if 检查analysis_options.yaml 并启用了严格设置strict-casts: true、strict-inference: true、strict-raw-types: true// ignore:)有注释解释原因flutter analyze 在 CI 中运行,失败阻止合并prefer_const_constructors — Widget 树中的性能avoid_print — 使用适当的日志unawaited_futures — 防止即发即忘的异步 bugprefer_final_locals — 变量级别的不可变性always_declare_return_types — 显式契约avoid_catches_without_on_clauses — 特定的错误处理always_use_package_imports — 一致的导入风格下表将通用原则映射到流行方案中的实现。使用此表将审查规则调整为项目使用的方案。
| 原则 | BLoC/Cubit | Riverpod | Provider | GetX | MobX | Signals | 内置 |
|---|---|---|---|---|---|---|---|
| 状态容器 | Bloc/Cubit | Notifier/AsyncNotifier | ChangeNotifier | GetxController | Store | signal() | StatefulWidget |
| UI 消费者 | BlocBuilder | ConsumerWidget | Consumer | Obx/GetBuilder | Observer | Watch | setState |
| 选择器 | BlocSelector/buildWhen | ref.watch(p.select(...)) | Selector | N/A | computed | computed() | N/A |
| 副作用 | BlocListener | ref.listen | Consumer 回调 | ever()/once() | reaction | effect() | 回调 |
| 释放 | 通过 BlocProvider 自动 | .autoDispose | 通过 Provider 自动 | onClose() | ReactionDisposer | 手动 | dispose() |
| 测试 | blocTest() | ProviderContainer | 直接 ChangeNotifier | 测试中 Get.put | 直接 store | 直接 signal | Widget 测试 |
npx claudepluginhub aaione/everything-claude-code-zhReviews Flutter/Dart code with library-agnostic checklist for widget best practices, state management patterns, Dart idioms, performance, accessibility, security, and clean architecture.
Reviews Flutter/Dart code for widget best practices, state management, Dart idioms, performance, accessibility, security, and clean architecture regardless of libraries used.
Provides expert Flutter/Dart patterns for cross-platform mobile apps including feature-first project structure, const widget best practices, and Riverpod/Bloc state management.