docs/zh-CN/skills/flutter-dart-code-review/SKILL.md
库无关的Flutter/Dart代码审查清单,涵盖Widget最佳实践、状态管理模式(BLoC、Riverpod、Provider、GetX、MobX、Signals)、Dart惯用法、性能、可访问性、安全性和整洁架构。
npx skillsauth add ysyecust/everything-claude-code flutter-dart-code-reviewInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
适用于审查 Flutter/Dart 应用程序的全面、与库无关的清单。无论使用哪种状态管理方案、路由库或依赖注入框架,这些原则都适用。
pubspec.yaml 是干净的 —— 没有未使用的依赖项,版本已适当固定analysis_options.yaml 包含严格的 lint 规则集,并启用了严格的分析器设置print() 语句 —— 使用 dart:developer log() 或日志包.g.dart, .freezed.dart, .gr.dart) 是最新的或在 .gitignore 中dynamic —— 启用 strict-casts, strict-inference, strict-raw-types!(感叹号操作符)而不是适当的空检查或 Dart 3 模式匹配 (if (value case var v?))this.fieldcatch (e) 没有 on 子句;应始终指定异常类型Error:Error 子类型表示错误,不应被捕获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*() 辅助方法被提取到单独的部件类中(支持元素重用、常量传播和框架优化)const 构造器 —— 防止不必要的重建const 字面量 (const [], const {})constValueKey 以在重新排序时保持状态GlobalKey —— 仅在确实需要跨树访问状态时使用build() 中使用 UniqueKey —— 它会强制每帧都重建ObjectKeyTheme.of(context).colorScheme —— 没有硬编码的 Colors.red 或十六进制值Theme.of(context).textTheme —— 没有内联的 TextStyle 和原始字体大小build() 中没有网络调用、文件 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)// BAD — boolean flag soup allows impossible states
class UserState {
bool isLoading = false;
bool hasError = false; // isLoading && hasError is representable!
User? user;
}
// GOOD (immutable approach) — sealed types make impossible states unrepresentable
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);
}
// GOOD (reactive approach) — observable enum + data, mutations via reactivity API
// enum UserStatus { initial, loading, loaded, error }
// Use your solution's observable/signal to wrap status and data separately
const 部件来阻止重建在树中传播.listen()) 在 dispose() / close() 中被取消.listen())setState 之前检查 mountedawait 之后使用 BuildContext 而不检查 context.mounted(Flutter 3.7+)—— 过时的上下文会导致崩溃BuildContext 绝不存储在单例、状态管理器或静态字段中setState, ValueNotifier)setState() —— 将状态变化局部化const 部件来阻止重建传播RepaintBoundaryAnimatedBuilder 的 child 参数处理独立于动画的子树build() 中对大型集合进行排序、过滤或映射 —— 在状态管理层计算build() 中编译正则表达式MediaQuery.of(context) 的使用是具体的(例如,MediaQuery.sizeOf(context))cacheWidth/cacheHeight 的 Image.asset 以按显示尺寸解码ListView.builder / GridView.builder 代替 ListView(children: [...])(对于小型、静态列表,具体构造器是可以的)deferred as)Opacity 部件 —— 使用 AnimatedOpacity 或 FadeTransitionoperator == —— 使用 const 构造器代替IntrinsicHeight, IntrinsicWidth) 谨慎使用(额外的布局传递)pumpWidget 和 pump 被正确用于异步操作find.byType、find.text、find.byKey 使用得当pumpAndSettle 或显式的 pump(Duration)Semantics 小部件在自动标签不足时提供屏幕阅读器标签ExcludeSemantics 处理纯装饰性元素MergeSemantics 将相关小部件组合成单个可访问元素semanticLabel 属性onPressed 回调——每个按钮都有作用或处于禁用状态SafeArea 小部件处理状态栏和安全区域AndroidManifest.xml 和 Info.plist 中声明LayoutBuilder 或 MediaQuery 实现响应式布局Flexible、Expanded、FittedBox--dart-define,.env 文件从 VCS 中排除,或使用编译时配置.gitignore^1.2.3)——允许兼容性更新flutter pub outdated 以跟踪过时的依赖项pubspec.yaml 中没有依赖项覆盖——仅用于带有注释/问题链接的临时修复package:other/src/internal.dart(破坏 Dart 包封装)path: ../../ 相对字符串analysis_options.yamlNavigator.push 和声明式路由器Map<String, dynamic> 或 Object? 转换FlutterError.onError 以捕获框架错误(构建、布局、绘制)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——小部件树中的性能avoid_print——使用适当的日志记录unawaited_futures——防止即发即弃的异步错误prefer_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 | 小部件测试 |
documentation
将签证申请文件(图片)翻译成英文,并创建包含原文和译文的双语PDF
content-media
视频与音频的查看、理解与行动。查看:从本地文件、URL、RTSP/直播源或实时录制桌面获取内容;返回实时上下文和可播放流链接。理解:提取帧,构建视觉/语义/时间索引,并通过时间戳和自动剪辑搜索片段。行动:转码和标准化(编解码器、帧率、分辨率、宽高比),执行时间线编辑(字幕、文本/图像叠加、品牌化、音频叠加、配音、翻译),生成媒体资源(图像、音频、视频),并为直播流或桌面捕获的事件创建实时警报。
data-ai
AI辅助的视频编辑工作流程,用于剪辑、构建和增强实拍素材。涵盖从原始拍摄到FFmpeg、Remotion、ElevenLabs、fal.ai,再到Descript或CapCut最终润色的完整流程。适用于用户想要编辑视频、剪辑素材、制作vlog或构建视频内容的情况。
development
Claude Code 会话的全面验证系统。