文章目录
-
- 每日一句正能量
- 一、前言:跨端开发的"最后一公里"难题
- [二、环境准备:AtomCode 与 Flutter 工具链](#二、环境准备:AtomCode 与 Flutter 工具链)
-
- [2.1 安装 AtomCode](#2.1 安装 AtomCode)
- [2.2 配置模型提供方](#2.2 配置模型提供方)
- [2.3 确认 Flutter 环境](#2.3 确认 Flutter 环境)
- 三、项目初始化:一句话生成跨端工程骨架
-
- [3.1 创建项目目录并启动 AtomCode](#3.1 创建项目目录并启动 AtomCode)
- [3.2 用自然语言描述需求](#3.2 用自然语言描述需求)
- [3.3 AtomCode 的自动化执行流程](#3.3 AtomCode 的自动化执行流程)
- [四、核心架构:Riverpod 3.x + GoRouter + Clean Architecture](#四、核心架构:Riverpod 3.x + GoRouter + Clean Architecture)
-
- [4.1 Riverpod 3.x 代码生成版](#4.1 Riverpod 3.x 代码生成版)
- [4.2 GoRouter 深层链接配置](#4.2 GoRouter 深层链接配置)
- [4.3 离线优先的数据层](#4.3 离线优先的数据层)
- 五、多端适配:一套代码,四种体验
-
- [5.1 平台检测与自适应布局](#5.1 平台检测与自适应布局)
- [5.2 桌面端多窗口支持(实验性)](#5.2 桌面端多窗口支持(实验性))
- [5.3 Web 端优化](#5.3 Web 端优化)
- [六、AI 驱动的 UI 开发:从描述到 Widget](#六、AI 驱动的 UI 开发:从描述到 Widget)
-
- [6.1 生成任务卡片组件](#6.1 生成任务卡片组件)
- [6.2 自动生成 Widget 测试](#6.2 自动生成 Widget 测试)
- [七、代码图谱:理解大型 Flutter 项目的利器](#七、代码图谱:理解大型 Flutter 项目的利器)
-
- [7.1 实战:安全重构 Task 模型](#7.1 实战:安全重构 Task 模型)
- 八、项目指令文件:团队协作的规范基石
- [九、CI/CD 与多端部署](#九、CI/CD 与多端部署)
-
- [9.1 AtomGit CI 配置](#9.1 AtomGit CI 配置)
- [9.2 本地预检脚本](#9.2 本地预检脚本)
- [十、总结:AI 原生跨端开发的未来](#十、总结:AI 原生跨端开发的未来)

每日一句正能量
"烟火起,照人间,举杯敬此年。"
此年是旧年,也是即将成为旧年的新年。烟火一瞬,照亮人间,也照亮杯中的倒影。
一、前言:跨端开发的"最后一公里"难题
Flutter 作为 Google 开源的跨端 UI 框架,在 2026 年已经覆盖了 iOS、Android、Web、Windows、macOS、Linux 乃至嵌入式系统(如 2026 Toyota RAV4 车载系统、LG webOS 设备)。根据官方数据,Flutter 月活开发者已超过 150 万,pub.dev 生态在过去 30 天内产生了超过 13 亿次包下载。
然而,Flutter 的"一次编写,多端运行"愿景在实际落地中仍面临诸多挑战:
- 项目结构复杂 :大型 Flutter 项目需要合理划分
lib/目录、管理状态层、路由层、网络层、数据层 - 状态管理选型困难:BLoC、Riverpod、Provider、GetX 各有优劣,团队需要统一规范
- 多端适配繁琐:移动端与桌面端的交互差异、Web 端的 SEO 和路由处理、各平台的主题适配
- 测试覆盖不足:Widget 测试、集成测试、Golden 测试编写成本高,往往被忽略
AtomCode 的出现,为上述难题提供了系统性的解法。作为 MIT 开源的终端 AI 编码智能体,AtomCode 内置 21 个工具(含 8 个代码图谱工具),支持自主读取文件、编辑代码、运行命令、验证结果。更重要的是,AtomCode 能够调用 list_symbols、find_references、trace_callers 等代码图谱工具,真正"理解"大型 Flutter 代码库的依赖关系,而不仅仅是文本补全。
本文将以一个真实的**任务管理应用(TaskMaster)**为例,完整演示如何利用 AtomCode,从自然语言需求描述开始,生成可在 iOS、Android、Web、macOS 四端运行的 Flutter 项目。
二、环境准备:AtomCode 与 Flutter 工具链
2.1 安装 AtomCode
AtomCode 支持 macOS、Linux、Windows、HarmonyOS,包体小于 50MB,秒级启动:
bash
# macOS / Linux 一键安装
curl -fsSL https://raw.atomgit.com/atomgit_atomcode/atomcode/raw/main/scripts/install.sh | sh
# 验证安装
atomcode --version
# 输出:atomcode v5.0.6
2.2 配置模型提供方
Flutter 开发涉及大量 UI 代码和状态管理逻辑,建议选用代码能力强的模型。本文使用 DeepSeek V3(编码能力较上一版本增强 30% 以上):
bash
atomcode
> /provider
# 选择 DeepSeek,输入 API Key
# 模型选择 deepseek-v4-flash 或 deepseek-chat
2.3 确认 Flutter 环境
确保本地已安装 Flutter 3.47+ 和 Dart 3.12+:
bash
flutter --version
# Flutter 3.47.0 • channel stable
# Dart 3.12.0
AtomCode 会自动检测当前目录结构,识别出这是一个 Flutter 项目环境,为后续任务规划做准备。
三、项目初始化:一句话生成跨端工程骨架
3.1 创建项目目录并启动 AtomCode
bash
mkdir taskmaster && cd taskmaster
atomcode
3.2 用自然语言描述需求
在 AtomCode 交互界面中输入:
帮我初始化一个 Flutter 跨端任务管理应用,要求:
1. 使用 Flutter 3.47 + Dart 3.12
2. 状态管理使用 Riverpod 3.x(代码生成版),支持自动缓存和依赖注入
3. 路由使用 GoRouter,支持深层链接和路由守卫
4. 网络层使用 Dio + Retrofit,支持请求拦截、错误处理和自动重试
5. 数据层使用 Hive 做本地缓存,支持离线优先
6. UI 使用 Material 3 设计规范,支持亮色/暗色主题切换
7. 项目结构遵循 Clean Architecture:presentation / domain / data 三层
8. 支持 iOS、Android、Web、macOS 四端运行
9. 初始化完成后运行 flutter analyze 和 flutter test,确保无错误
3.3 AtomCode 的自动化执行流程
AtomCode 收到指令后,会进入智能体循环(Smart Agent Loop),自动执行以下步骤:
规划 分析任务范围 → 拆解为 12 个子任务
读取 检测当前目录为空,确认从零开始
执行 运行 flutter create --platforms=ios,android,web,macos . 创建项目
执行 编辑 pubspec.yaml,添加 Riverpod、GoRouter、Dio、Retrofit、Hive 等依赖
执行 运行 flutter pub get 安装依赖
执行 生成 lib/ 目录下的 Clean Architecture 结构
执行 生成 Riverpod Provider 代码(含 @riverpod 注解和代码生成配置)
执行 生成 GoRouter 路由配置
执行 生成 Dio 网络层封装(含拦截器、错误处理)
执行 生成 Hive 本地存储适配器
执行 生成 Material 3 主题配置(支持亮/暗模式)
执行 生成示例页面(任务列表页、任务详情页、新增任务页)
运行 flutter pub run build_runner build 生成 Riverpod 代码
运行 flutter analyze 验证无静态错误
运行 flutter test 验证测试通过
整个过程无需人工干预,约 5-8 分钟即可完成。生成的项目结构如下:
taskmaster/
├── .atomcode.md # 项目指令文件
├── pubspec.yaml
├── lib/
│ ├── main.dart
│ ├── app.dart # 应用入口,含 ProviderScope
│ ├── router.dart # GoRouter 配置
│ ├── theme.dart # Material 3 主题
│ ├── core/ # 核心工具
│ │ ├── constants.dart
│ │ ├── errors/
│ │ │ └── exceptions.dart
│ │ └── utils/
│ │ └── date_formatter.dart
│ ├── presentation/ # 表现层
│ │ ├── pages/
│ │ │ ├── task_list_page.dart
│ │ │ ├── task_detail_page.dart
│ │ │ └── add_task_page.dart
│ │ ├── widgets/
│ │ │ ├── task_card.dart
│ │ │ ├── task_filter_chip.dart
│ │ │ └── empty_state.dart
│ │ └── providers/ # Riverpod Providers
│ │ ├── task_list_provider.dart
│ │ └── task_list_provider.g.dart
│ ├── domain/ # 领域层
│ │ ├── entities/
│ │ │ └── task.dart
│ │ ├── repositories/
│ │ │ └── task_repository.dart
│ │ └── usecases/
│ │ ├── get_tasks.dart
│ │ ├── add_task.dart
│ │ └── toggle_task.dart
│ └── data/ # 数据层
│ ├── models/
│ │ └── task_model.dart
│ ├── datasources/
│ │ ├── remote_task_datasource.dart
│ │ └── local_task_datasource.dart
│ └── repositories/
│ └── task_repository_impl.dart
├── test/
│ ├── widget/
│ │ └── task_list_page_test.dart
│ └── unit/
│ └── domain/
│ └── get_tasks_test.dart
└── macos/、ios/、android/、web/ # 平台目录
四、核心架构:Riverpod 3.x + GoRouter + Clean Architecture
4.1 Riverpod 3.x 代码生成版
Riverpod 3.x 在 2026 年已经成为 Flutter 状态管理的主流选择之一,其统一了 Ref API,支持自动重试和离线持久化。
AtomCode 生成的 Task 实体和 Provider:
dart
// lib/domain/entities/task.dart
import 'package:freezed_annotation/freezed_annotation.dart';
part 'task.freezed.dart';
part 'task.g.dart';
@freezed
class Task with _$Task {
const factory Task({
required String id,
required String title,
String? description,
required bool isCompleted,
required DateTime createdAt,
DateTime? dueDate,
TaskPriority? priority,
}) = _Task;
factory Task.fromJson(Map<String, dynamic> json) => _$TaskFromJson(json);
}
enum TaskPriority { low, medium, high }
dart
// lib/presentation/providers/task_list_provider.dart
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:taskmaster/domain/entities/task.dart';
import 'package:taskmaster/domain/usecases/get_tasks.dart';
part 'task_list_provider.g.dart';
@riverpod
class TaskList extends _$TaskList {
@override
Future<List<Task>> build() async {
// Riverpod 3.x 自动缓存,依赖变化时自动刷新
final getTasks = ref.watch(getTasksProvider);
return getTasks.call();
}
Future<void> addTask(String title, {String? description, DateTime? dueDate}) async {
final addTask = ref.read(addTaskProvider);
await addTask.call(title: title, description: description, dueDate: dueDate);
// 使当前 Provider 失效,触发自动重取
ref.invalidateSelf();
}
Future<void> toggleTask(String id) async {
final toggleTask = ref.read(toggleTaskProvider);
await toggleTask.call(id: id);
ref.invalidateSelf();
}
}
AtomCode 会自动配置 build_runner 并生成 .g.dart 文件,开发者无需手动处理代码生成。
4.2 GoRouter 深层链接配置
dart
// lib/router.dart
import 'package:go_router/go_router.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'presentation/pages/task_list_page.dart';
import 'presentation/pages/task_detail_page.dart';
import 'presentation/pages/add_task_page.dart';
final routerProvider = Provider<GoRouter>((ref) {
return GoRouter(
initialLocation: '/',
routes: [
GoRoute(
path: '/',
builder: (context, state) => const TaskListPage(),
),
GoRoute(
path: '/task/:id',
builder: (context, state) {
final id = state.pathParameters['id']!;
return TaskDetailPage(taskId: id);
},
),
GoRoute(
path: '/add',
builder: (context, state) => const AddTaskPage(),
),
],
// 路由守卫:检查必要权限或状态
redirect: (context, state) {
// 可在此添加认证检查
return null;
},
);
});
4.3 离线优先的数据层
AtomCode 生成的数据层实现了远程数据源 + 本地数据源 + 仓库模式:
dart
// lib/data/repositories/task_repository_impl.dart
import 'package:taskmaster/domain/entities/task.dart';
import 'package:taskmaster/domain/repositories/task_repository.dart';
import 'package:taskmaster/data/datasources/remote_task_datasource.dart';
import 'package:taskmaster/data/datasources/local_task_datasource.dart';
class TaskRepositoryImpl implements TaskRepository {
final RemoteTaskDataSource _remote;
final LocalTaskDataSource _local;
TaskRepositoryImpl(this._remote, this._local);
@override
Future<List<Task>> getTasks() async {
try {
// 优先从远程获取
final tasks = await _remote.getTasks();
// 缓存到本地
await _local.cacheTasks(tasks);
return tasks;
} catch (e) {
// 网络失败时回退到本地缓存
return _local.getCachedTasks();
}
}
@override
Future<void> addTask(Task task) async {
await _remote.addTask(task);
await _local.cacheTask(task);
}
// ... 其他方法
}
五、多端适配:一套代码,四种体验
Flutter 的跨端能力不仅在于"能运行",更在于"体验原生"。AtomCode 在生成代码时会自动处理多端差异:
5.1 平台检测与自适应布局
dart
// lib/presentation/pages/task_list_page.dart
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
class TaskListPage extends ConsumerWidget {
const TaskListPage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final tasksAsync = ref.watch(taskListProvider);
// 自适应布局:桌面端使用侧边栏,移动端使用底部导航
final isDesktop = switch (defaultTargetPlatform) {
TargetPlatform.macOS || TargetPlatform.windows || TargetPlatform.linux => true,
_ => false,
};
return Scaffold(
appBar: AppBar(
title: const Text('TaskMaster'),
centerTitle: !isDesktop,
actions: [
IconButton(
icon: const Icon(Icons.brightness_6),
onPressed: () {
// 切换主题
},
),
],
),
body: isDesktop
? _DesktopLayout(tasksAsync: tasksAsync)
: _MobileLayout(tasksAsync: tasksAsync),
floatingActionButton: isDesktop
? null // 桌面端使用键盘快捷键或侧边栏按钮
: FloatingActionButton(
onPressed: () => context.push('/add'),
child: const Icon(Icons.add),
),
);
}
}
5.2 桌面端多窗口支持(实验性)
Flutter 3.44 引入了实验性的多窗口 API,Canonical 作为桌面端的主要维护者,正在推进 Linux、Windows、macOS 的窗口管理功能。
AtomCode 可以为桌面端生成多窗口支持代码:
dart
// 桌面端专用:弹出独立任务详情窗口
Future<void> openTaskDetailWindow(String taskId) async {
if (Platform.isMacOS || Platform.isWindows || Platform.isLinux) {
// 使用 Flutter 3.44+ 的 Windowing API
// 创建独立的子窗口显示任务详情
} else {
// 移动端使用路由导航
// context.push('/task/$taskId');
}
}
5.3 Web 端优化
对于 Web 端,AtomCode 会自动处理:
base-href配置,确保部署到子路径时资源加载正确prefers-reduced-motion媒体查询,支持无障碍访问- 响应式布局,适配不同屏幕尺寸
六、AI 驱动的 UI 开发:从描述到 Widget
Flutter 的核心优势在于丰富的 Widget 系统。AtomCode 能够将自然语言 UI 描述转化为精确的 Widget 代码。
6.1 生成任务卡片组件
创建一个 TaskCard 组件,要求:
1. 显示任务标题、描述(最多两行)、截止日期、优先级标签
2. 左侧有圆形复选框,点击切换完成状态
3. 优先级用颜色区分:low=绿色, medium=橙色, high=红色
4. 已完成的任务标题带删除线,整体透明度降低
5. 支持长按弹出菜单:编辑、删除
6. 使用 Material 3 的 Card 和 InkWell
7. 编写对应的 Widget 测试
AtomCode 生成的代码:
dart
// lib/presentation/widgets/task_card.dart
import 'package:flutter/material.dart';
import 'package:taskmaster/domain/entities/task.dart';
class TaskCard extends StatelessWidget {
final Task task;
final ValueChanged<bool?> onToggle;
final VoidCallback onEdit;
final VoidCallback onDelete;
const TaskCard({
super.key,
required this.task,
required this.onToggle,
required this.onEdit,
required this.onDelete,
});
Color _getPriorityColor(TaskPriority priority) {
return switch (priority) {
TaskPriority.low => Colors.green,
TaskPriority.medium => Colors.orange,
TaskPriority.high => Colors.red,
};
}
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final isCompleted = task.isCompleted;
return Card(
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
child: InkWell(
onLongPress: () => _showContextMenu(context),
borderRadius: BorderRadius.circular(12),
child: Padding(
padding: const EdgeInsets.all(16),
child: Row(
children: [
Checkbox(
value: isCompleted,
onChanged: onToggle,
shape: const CircleBorder(),
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
task.title,
style: theme.textTheme.titleMedium?.copyWith(
decoration: isCompleted ? TextDecoration.lineThrough : null,
color: isCompleted ? theme.colorScheme.onSurface.withOpacity(0.6) : null,
),
),
if (task.description != null) ...[
const SizedBox(height: 4),
Text(
task.description!,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: theme.textTheme.bodyMedium?.copyWith(
color: theme.colorScheme.onSurface.withOpacity(0.6),
),
),
],
const SizedBox(height: 8),
Row(
children: [
if (task.priority != null)
Chip(
label: Text(
task.priority!.name.toUpperCase(),
style: const TextStyle(fontSize: 10),
),
backgroundColor: _getPriorityColor(task.priority!).withOpacity(0.2),
side: BorderSide.none,
padding: EdgeInsets.zero,
labelPadding: const EdgeInsets.symmetric(horizontal: 8),
),
const SizedBox(width: 8),
if (task.dueDate != null)
Icon(
Icons.calendar_today,
size: 14,
color: theme.colorScheme.onSurface.withOpacity(0.5),
),
],
),
],
),
),
],
),
),
),
);
}
void _showContextMenu(BuildContext context) {
showModalBottomSheet(
context: context,
builder: (context) => SafeArea(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
leading: const Icon(Icons.edit),
title: const Text('编辑'),
onTap: () {
Navigator.pop(context);
onEdit();
},
),
ListTile(
leading: const Icon(Icons.delete, color: Colors.red),
title: const Text('删除', style: TextStyle(color: Colors.red)),
onTap: () {
Navigator.pop(context);
onDelete();
},
),
],
),
),
);
}
}
6.2 自动生成 Widget 测试
dart
// test/widget/task_card_test.dart
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:taskmaster/domain/entities/task.dart';
import 'package:taskmaster/presentation/widgets/task_card.dart';
void main() {
testWidgets('TaskCard displays task information correctly', (tester) async {
final task = Task(
id: '1',
title: '完成 Flutter 文章',
description: '撰写 AtomCode + Flutter 实战文章',
isCompleted: false,
createdAt: DateTime.now(),
priority: TaskPriority.high,
);
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: TaskCard(
task: task,
onToggle: (_) {},
onEdit: () {},
onDelete: () {},
),
),
),
);
expect(find.text('完成 Flutter 文章'), findsOneWidget);
expect(find.text('HIGH'), findsOneWidget);
expect(find.byType(Checkbox), findsOneWidget);
});
testWidgets('TaskCard shows strikethrough for completed task', (tester) async {
final task = Task(
id: '2',
title: '已完成任务',
isCompleted: true,
createdAt: DateTime.now(),
);
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: TaskCard(
task: task,
onToggle: (_) {},
onEdit: () {},
onDelete: () {},
),
),
),
);
final text = tester.widget<Text>(find.text('已完成任务'));
expect(text.style?.decoration, TextDecoration.lineThrough);
});
}
AtomCode 生成测试后会自动运行 flutter test,确保所有用例通过。
七、代码图谱:理解大型 Flutter 项目的利器
当项目规模扩大时,理解 Widget 树、Provider 依赖图和路由结构变得困难。AtomCode 的 8 个代码图谱工具在此发挥关键作用:
| 工具 | Flutter 项目应用场景 |
|---|---|
list_symbols |
列出某文件中所有类、方法、变量,快速了解模块接口 |
find_references |
查找某个 Provider 在哪些页面被 watch 或 read |
trace_callers |
追溯某个 API 调用是从哪个 UI 事件触发的 |
trace_callees |
分析某个 UseCase 调用了哪些 Repository 方法 |
file_deps |
分析 Dart 文件之间的 import 依赖,发现循环依赖 |
blast_radius |
评估修改某个 Model 字段会影响多少 Widget 和测试 |
7.1 实战:安全重构 Task 模型
假设我们需要给 Task 实体新增 tags 字段,但不确定会影响多少地方。在 AtomCode 中输入:
给 Task 实体新增 List<String> tags 字段,要求:
1. 使用 find_references 查找 Task 的所有引用位置
2. 使用 blast_radius 分析影响范围
3. 更新所有受影响的 Model、Provider、Widget 和测试
4. 确保 Hive 适配器同步更新
5. 运行所有测试验证
AtomCode 会自动调用代码图谱工具,按依赖顺序逐步修改:
- 修改
domain/entities/task.dart(Freezed 实体) - 修改
data/models/task_model.dart(数据模型) - 修改
data/datasources/local_task_datasource.dart(Hive 适配器) - 修改
presentation/widgets/task_card.dart(UI 显示标签) - 更新所有相关测试
这种影响范围分析 + 自动化重构的能力,在传统开发中需要开发者手动搜索和修改数十个文件,耗时且容易遗漏。
八、项目指令文件:团队协作的规范基石
在团队协作中,保持 Flutter 项目架构一致至关重要。AtomCode 支持通过 .atomcode.md 文件注入项目级上下文:

markdown
# TaskMaster 项目指令
## 架构规范
- 严格遵循 Clean Architecture:Presentation → Domain → Data
- 状态管理统一使用 Riverpod 3.x,禁止混用 Provider / GetX
- 所有实体使用 Freezed + JSON Serializable,禁止手写 fromJson/toJson
- 网络请求统一封装在 data/datasources/ 中,使用 Dio 拦截器处理 Token 刷新
## UI 规范
- 所有页面使用 ConsumerWidget 或 ConsumerStatefulWidget
- 颜色不使用硬编码,必须从 Theme.of(context) 获取
- 间距使用 4 的倍数(4, 8, 12, 16, 24, 32)
- 图标使用 Material Symbols,不使用 Cupertino 图标(除平台特定场景外)
## 路由规范
- 所有路由定义在 router.dart 中,禁止在页面内直接 Navigator.push
- 深层链接路径使用小写 + 下划线,如 /task_detail/:id
- 路由守卫用于权限检查,禁止在页面内重复检查
## 测试规范
- 所有 Widget 必须编写 Widget 测试
- 所有 UseCase 必须编写单元测试
- 测试覆盖率不低于 70%
- 使用 golden_toolkit 进行 Golden 测试(关键页面)
## 多端适配规范
- 使用 defaultTargetPlatform 判断平台,禁止使用 dart:io 的 Platform.isXxx(Web 不支持)
- 桌面端布局使用 Row + Expanded,移动端使用 Column
- Web 端路由使用 --base-href 配置
## 常用命令
- 代码生成:flutter pub run build_runner build --delete-conflicting-outputs
- 运行测试:flutter test
- 静态分析:flutter analyze
- 运行 Web:flutter run -d chrome --web-port=8080
- 构建 macOS:flutter build macos
当新成员加入团队时,只需阅读 .atomcode.md 即可快速理解项目规范。而 AtomCode 在生成新代码时,会自动遵循这些规范,无需反复在 Prompt 中强调。
九、CI/CD 与多端部署
9.1 AtomGit CI 配置
Flutter 项目的 CI/CD 需要处理多平台构建。以下是在 AtomGit CI 中配置 Flutter 自动构建的示例:
yaml
# .atomgit-ci.yml
stages:
- analyze
- test
- build
variables:
FLUTTER_VERSION: "3.47.0"
analyze:
stage: analyze
image: ghcr.io/cirruslabs/flutter:${FLUTTER_VERSION}
script:
- flutter pub get
- flutter pub run build_runner build --delete-conflicting-outputs
- flutter analyze
- flutter format --set-exit-if-changed lib/ test/
test:
stage: test
image: ghcr.io/cirruslabs/flutter:${FLUTTER_VERSION}
script:
- flutter pub get
- flutter test --coverage
coverage: '/\s*(\d+\.\d+)%\s*of\s*all\s*lines/'
artifacts:
paths:
- coverage/
build_web:
stage: build
image: ghcr.io/cirruslabs/flutter:${FLUTTER_VERSION}
script:
- flutter pub get
- flutter build web --release --base-href /taskmaster/
artifacts:
paths:
- build/web/
only:
- main
9.2 本地预检脚本
在提交代码前,使用 AtomCode Headless 模式执行预检:
bash
#!/bin/bash
# scripts/pre-commit.sh
echo "🚀 运行 AtomCode Flutter 预检..."
atomcode -p "检查当前 Flutter 项目的编译错误、静态分析问题,运行所有测试确保通过,然后格式化代码" --max-turns 20
if [ $? -ne 0 ]; then
echo "❌ 预检失败,请修复问题后重新提交"
exit 1
fi
echo "✅ 预检通过"
十、总结:AI 原生跨端开发的未来
通过本文的完整实践,我们见证了 AtomCode 如何重塑 Flutter 跨端开发的工作流:
- 初始化阶段:一句话生成支持 iOS、Android、Web、macOS 四端的完整项目骨架,省去数小时的配置时间
- 架构阶段:自动生成 Clean Architecture 分层、Riverpod 3.x 状态管理、GoRouter 路由配置
- 开发阶段:自然语言描述 UI 需求,AI 生成类型安全的 Widget 和测试
- 适配阶段:自动处理多端布局差异、主题切换、平台特定逻辑
- 维护阶段:代码图谱工具辅助理解大型代码库,安全重构影响范围可控
- 协作阶段 :
.atomcode.md项目指令文件确保团队规范一致 - 部署阶段:Headless 模式无缝接入 CI/CD,自动化构建多端产物
Flutter 的"一次编写,多端运行"愿景,在 AtomCode 的 AI 驱动下,真正从"能运行"进化到了"高效运行、规范运行、可持续维护"。对于跨端开发团队而言,这不仅是效率的提升,更是开发范式的转变------从"手写每一行 Dart 代码"到"描述需求、审查架构、验收多端产物"。
AtomCode 作为 MIT 开源项目,代码完全透明,社区活跃。如果你正在寻找一条高效、规范、可落地的 Flutter 跨端开发路径,不妨从 AtomCode 开始你的 AI 驱动之旅。
转载自:https://blog.csdn.net/sghtgjfhv/article/details/163862593
欢迎 👍点赞✍评论⭐收藏,欢迎指正