mcpField
F
flutter-dev

flutter-dev

github.com/bogdanustyak开发0176 次安装40 周前更新
代码仓库

关于 flutter-dev

为 Flutter 和 Dart 开发提供遵循 Flutter 官方团队实践的指导,适用于编写和维护应用的开发者。内容涵盖代码组织、状态管理、布局、导航、测试和无障碍设计。

主要功能

  1. 01遵循 SOLID 与 Dart 风格规范
  2. 02建议分层或按功能组织项目
  3. 03指导内置状态管理方案
  4. 04涵盖响应式布局与导航
  5. 05提供测试和代码分析建议
  6. 06包含无障碍与主题实践

适用场景

  1. 01规划 Flutter 项目结构
  2. 02实现响应式界面与导航
  3. 03选择状态管理和异步模式
  4. 04为应用编写测试并检查代码

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/bogdanustyak/flutter-expert-skill --skill flutter-dev

安装后在 Claude Code 中输入/flutter-dev确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

README.md
references/
navigation_patterns.md
theme_patterns.md
state_patterns.md

详细介绍

Flutter 开发专家

遵循 Flutter 团队的官方最佳实践,为 Flutter 和 Dart 开发提供专家指导。

核心开发原则

代码理念
  • 在整个代码库中贯彻 SOLID 原则
  • 使用函数式和声明式模式,编写简洁、现代、技术性强的 Dart 代码
  • 构建复杂组件和逻辑时,优先使用组合而非继承
  • 优先使用不可变数据结构,尤其是组件(尽可能使用 StatelessWidget)
  • 使用适当的状态管理方式,将临时状态与应用状态分离
  • 保持函数简短且职责单一(尽量少于 20 行)
  • 使用有意义且明确的名称,避免使用缩写
项目结构假设
  • 使用标准 Flutter 项目结构,以 lib/main.dart 作为入口点
  • 按逻辑分层组织:表现层(组件/屏幕)、领域层(业务逻辑)、数据层(模型/API 客户端)、核心层(工具/扩展)
  • 对于较大的项目:按功能组织,每个功能包含表现层/领域层/数据层子文件夹

交互指南

生成代码时:

  • 解释 Dart 特有的功能(空安全、futures、streams)
  • 如果请求含糊,请询问功能和目标平台的具体信息
  • 建议使用 pub.dev 上的新依赖项时,说明其优点
  • 使用 dart format 工具统一格式
  • 使用 dart fix 工具自动修复常见错误
  • 使用配置了推荐规则的 Dart 代码检查工具发现问题

代码质量标准

样式规则
  • 行长度:不超过 80 个字符
  • 命名约定:
    • 类使用 PascalCase
    • 成员/变量/函数/枚举使用 camelCase
    • 文件使用 snake_case
  • 不要添加行尾注释
  • 简单的单行函数使用箭头语法
错误处理
  • 预判并处理潜在错误,绝不静默失败
  • 使用 try-catch 代码块和适当的异常类型
  • 针对特定代码情形使用自定义异常
  • 正确使用 async/await,并进行可靠的错误处理
文档
  • 为所有公共 API(类、构造函数、方法、顶层函数)添加 dartdoc 注释
  • 为复杂或不明显的代码编写清晰的注释
  • 使用 /// 编写文档注释
  • 以一个以句号结尾的单句摘要开头
  • 说明代码为何以特定方式编写,而非说明代码做了什么

Dart 最佳实践

类型系统与空安全
  • 编写健全的空安全代码
  • 利用 Dart 的空安全功能
  • 除非能确保值非空,否则避免使用 ! 运算符
  • 在能简化代码时使用模式匹配功能
  • 定义类过于繁琐时,使用记录返回多个类型
  • 优先使用穷尽式 switch 语句/表达式(无需 break)
异步编程
  • 对单次异步操作使用 Future、async、await
  • 对异步事件序列使用 Stream
  • 确保正确处理异步操作中的错误
类与库的组织
  • 在同一个库文件中定义相关类
  • 对于大型库:从单个顶层库导出较小的私有库
  • 将相关库放在同一个文件夹中

Flutter 最佳实践

组件设计
  • 组件(尤其是 StatelessWidget)不可变
  • UI 需要变化时,Flutter 会重建组件树
  • 优先组合较小的组件,而非扩展现有组件
  • 使用小型私有 Widget 类,而非返回组件的私有辅助方法
  • 将大型 build() 方法拆分为更小、可复用的私有 Widget 类
  • 尽可能使用 const 构造函数以减少重建
性能优化
  • 长列表使用 ListView.builder 或 SliverList(惰性加载)
  • 使用 compute() 在独立的 isolate 中运行耗时计算(例如 JSON 解析)
  • 避免在 build() 方法中执行开销较大的操作(网络请求、复杂计算)
  • 在 build() 方法中使用 const 构造函数,以尽可能减少重建
响应式设计
  • 使用 LayoutBuilder 或 MediaQuery 构建响应式 UI
  • 确保在不同屏幕尺寸下都能适配移动设备
  • 在移动端和 Web 平台上进行测试

状态管理

除非明确要求使用第三方方案,否则优先使用 Flutter 内置方案:

内置方案(按简洁程度排序)
  1. ValueNotifier + ValueListenableBuilder - 用于单个值的简单局部状态
final ValueNotifier<int> _counter = ValueNotifier<int>(0);

ValueListenableBuilder<int>(
  valueListenable: _counter,
  builder: (context, value, child) => Text('Count: $value'),
);
  1. ChangeNotifier + ListenableBuilder - 用于跨多个组件的复杂或共享状态
class CounterModel extends ChangeNotifier {
  int _count = 0;
  int get count => _count;
  void increment() {
    _count++;
    notifyListeners();
  }
}

ListenableBuilder(
  listenable: counterModel,
  builder: (context, child) => Text('${counterModel.count}'),
);
  1. Streams + StreamBuilder - 用于异步事件序列
  2. Futures + FutureBuilder - 用于单次异步操作
高级模式
  • MVVM:Model-View-ViewModel 模式,适用于稳健的应用
  • 依赖注入:使用手动构造函数注入,明确声明依赖项
  • Provider:仅在明确要求使用手动注入之外的 DI 时采用

导航

GoRouter(推荐)

使用 go_router 实现声明式导航、深度链接和 Web 支持:

// Add dependency
flutter pub add go_router

// Configure router
final GoRouter _router = GoRouter(
  routes: [
    GoRoute(
      path: '/',
      builder: (context, state) => const HomeScreen(),
      routes: [
        GoRoute(
          path: 'details/:id',
          builder: (context, state) {
            final String id = state.pathParameters['id']!;
            return DetailScreen(id: id);
          },
        ),
      ],
    ),
  ],
);

// Use in MaterialApp
MaterialApp.router(routerConfig: _router);
  • 配置 redirect 属性以处理身份验证流程
  • 用于支持深度链接的路由
Navigator(内置)

用于无需深度链接的短期屏幕(对话框、临时视图):

Navigator.push(context, MaterialPageRoute(builder: (context) => DetailsScreen()));
Navigator.pop(context);

包管理

使用 pub 工具
  • 添加依赖项:flutter pub add <package_name>
  • 添加开发依赖项:flutter pub add dev:<package_name>
  • 添加覆盖项:flutter pub add override:<package_name>:1.0.0
  • 移除依赖项:dart pub remove <package_name>
外部包
  • 在 pub.dev 上搜索合适且稳定的包
  • 推荐新依赖项时说明其优势

数据处理

JSON 序列化

使用 json_serializable 和 json_annotation:

import 'package:json_annotation/json_annotation.dart';
part 'user.g.dart';

@JsonSerializable(fieldRename: FieldRename.snake)
class User {
  final String firstName;
  final String lastName;
  
  User({required this.firstName, required this.lastName});
  
  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
  Map<String, dynamic> toJson() => _$UserToJson(this);
}
代码生成
  • 确保 build_runner 是开发依赖项
  • 修改后运行:dart run build_runner build --delete-conflicting-outputs

日志记录

使用 dart:developer 进行结构化日志记录:

import 'dart:developer' as developer;

// Simple messages
developer.log('User logged in successfully.');

// Structured error logging
try {
  // code
} catch (e, s) {
  developer.log(
    'Failed to fetch data',
    name: 'myapp.network',
    level: 1000, // SEVERE
    error: e,
    stackTrace: s,
  );
}

UI 与主题

Material Design 3 与 ThemeData

使用 ColorScheme.fromSeed() 创建协调的配色方案:

MaterialApp(
  theme: ThemeData(
    colorScheme: ColorScheme.fromSeed(
      seedColor: Colors.deepPurple,
      brightness: Brightness.light,
    ),
    textTheme: TextTheme(
      displayLarge: TextStyle(fontSize: 57, fontWeight: FontWeight.bold),
      bodyMedium: TextStyle(fontSize: 14, height: 1.4),
    ),
  ),
  darkTheme: ThemeData(
    colorScheme: ColorScheme.fromSeed(
      seedColor: Colors.deepPurple,
      brightness: Brightness.dark,
    ),
  ),
  themeMode: ThemeMode.system,
);
自定义主题扩展

用于标准 ThemeData 之外的自定义设计令牌:

@immutable
class MyColors extends ThemeExtension<MyColors> {
  const MyColors({required this.success, required this.danger});
  final Color? success;
  final Color? danger;
  
  @override
  ThemeExtension<MyColors> copyWith({Color? success, Color? danger}) {
    return MyColors(success: success ?? this.success, danger: danger ?? this.danger);
  }
  
  @override
  ThemeExtension<MyColors> lerp(ThemeExtension<MyColors>? other, double t) {
    if (other is! MyColors) return this;
    return MyColors(
      success: Color.lerp(success, other.success, t),
      danger: Color.lerp(danger, other.danger, t),
    );
  }
}

// Register in ThemeData
theme: ThemeData(
  extensions: [MyColors(success: Colors.green, danger: Colors.red)],
),

// Use in widgets
Container(color: Theme.of(context).extension<MyColors>()!.success)
字体

使用 google_fonts 包设置自定义字体:

flutter pub add google_fonts

final TextTheme appTextTheme = TextTheme(
  displayLarge: GoogleFonts.oswald(fontSize: 57, fontWeight: FontWeight.bold),
  titleLarge: GoogleFonts.roboto(fontSize: 22, fontWeight: FontWeight.w500),
  bodyMedium: GoogleFonts.openSans(fontSize: 14),
);
图像与资源

在 pubspec.yaml 中声明:

flutter:
  uses-material-design: true
  assets:
    - assets/images/
// Local images
Image.asset('assets/images/placeholder.png')

// Network images (always include error handling)
Image.network(
  'https://example.com/image.png',
  loadingBuilder: (context, child, progress) {
    if (progress == null) return child;
    return Center(child: CircularProgressIndicator());
  },
  errorBuilder: (context, error, stackTrace) => Icon(Icons.error),
)

布局最佳实践

灵活布局
  • Expanded:填满 Row/Column 中的剩余空间
  • Flexible:收缩以适应内容(不要与 Expanded 组合使用)
  • Wrap:溢出时自动换到下一行
  • SingleChildScrollView:用于大于视口的固定尺寸内容
  • ListView.builder/GridView.builder:用于长列表(延迟加载)
  • FittedBox:在父组件内缩放或适配单个子组件
  • LayoutBuilder:根据可用空间构建响应式布局
Stack 布局
  • Positioned:通过锚定边缘精确放置子组件
  • Align:使用对齐方式放置(例如,Alignment.center)
覆盖层

使用 OverlayPortal 在所有内容之上显示 UI 元素:

final _controller = OverlayPortalController();

OverlayPortal(
  controller: _controller,
  overlayChildBuilder: (context) => Positioned(
    top: 50,
    left: 10,
    child: Card(child: Text('Overlay content')),
  ),
  child: ElevatedButton(
    onPressed: _controller.toggle,
    child: Text('Toggle'),
  ),
)

视觉设计原则

设计指南
  • 构建美观、直观且符合现代设计的 UI
  • 确保适配不同屏幕尺寸(移动端和 Web)
  • 提供直观的导航
  • 运用字体层级(主视觉文本、标题、关键词)
  • 添加细腻的背景纹理,营造高级质感
  • 使用多层阴影增强层次感
  • 添加图标以提升理解度
  • 为交互元素添加阴影和色彩光晕效果
色彩指南
  • 60-30-10 法则:60% 主色/中性色、30% 次要色、10% 强调色
  • 对比度比例(WCAG 2.1):
    • 普通文本:至少 4.5:1
    • 大号文本(18pt 或 14pt 粗体):至少 3:1
  • 避免将互补色用于文本/背景(会造成视觉疲劳)
  • 谨慎使用互补色作为强调色
字体排印
  • 限制使用 1-2 种字体系列
  • 优先保证易读性(UI 正文使用无衬线字体)
  • 行高:字体大小的 1.4 倍至 1.6 倍
  • 行长:正文每行 45-75 个字符
  • 避免长篇文本全部使用大写字母

测试

测试类型
  • 单元测试:使用 package:test 测试领域逻辑、数据层和状态管理
  • Widget 测试:使用 package:flutter_test 测试 UI 组件
  • 集成测试:使用 package:integration_test 测试端到端流程
测试最佳实践
  • 遵循 Arrange-Act-Assert(Given-When-Then)模式
  • 优先使用 package:checks,以编写更具表现力的断言
  • 优先使用 fake/stub,而非 mock
  • 如有必要使用 mock:使用 mockito 或 mocktail
  • 力求实现较高的测试覆盖率
  • 编写易于测试的代码:使用 file、process、platform 包进行依赖注入
运行测试
flutter test

无障碍(A11y)

  • 色彩对比度:文本与背景的对比度至少为 4.5:1
  • 动态文本缩放:使用增大的系统字体测试 UI
  • 语义标签:使用 Semantics widget 设置清晰、明确的标签
  • 屏幕阅读器测试:使用 TalkBack(Android)和 VoiceOver(iOS)进行测试

分析与 Lint

在 analysis_options.yaml 中添加:

include: package:flutter_lints/flutter.yaml

linter:
  rules:
    # Add additional lint rules here

其他资源

如需查看详细模式和示例,请参阅:

  • references/navigation_patterns.md - 使用 GoRouter 的高级导航模式
  • references/state_patterns.md - 全面的状态管理示例
  • references/theme_patterns.md - 高级主题与样式模式

评论

支持 Markdown