Use Cases (更新: 2026/6/2)

Claude Code 用于 Flutter/Dart 开发:项目梳理、状态、测试与构建

用 Claude Code 做 Flutter/Dart 开发:梳理项目、管理 pubspec、修改状态、编写测试并验证构建。

Claude Code 用于 Flutter/Dart 开发:项目梳理、状态、测试与构建

在 Flutter/Dart 项目里,Claude Code 最有价值的地方不是一次生成一个漂亮组件,而是能读懂现有工程,把界面、状态、pubspec.yaml、平台差异、测试和构建检查串起来。Widget 可以理解为界面部件,state 是会改变界面显示的数据,pubspec 是记录 SDK 约束、依赖和资源文件的配置。只让 Claude Code “做一个页面”,往往会得到看起来可用、但 Android 权限、iOS plist、Web 资源路径或 widget test 没跟上的实现。

本文用一个购物车示例说明安全做法。harness 在这里指“给智能体搭好的工作脚手架”:允许编辑的文件、禁止事项、检查命令、验收标准和复查清单。官方资料建议以 Flutter CLIFlutter testingWidget testingFlutter pubspec optionsDart pubspecPlatform channelsClaude Code common workflows 为准。相关内容还可以读 React Native 开发测试策略CLAUDE.md 最佳实践

先画项目地图

第一步不要让 Claude Code 直接改代码。先让它阅读 pubspec.yamllib/test/、平台目录和分析配置,确认现有约定。这样可以避免它引入新的状态管理、错误的目录结构或不适合当前项目的测试风格。

请先阅读这个 Flutter 项目,不要编辑文件。
请报告:
1. pubspec.yaml 中的 SDK 约束、依赖、assets 设置
2. lib/ 下 UI、状态、data 层的组织方式
3. test/ 和 integration_test/ 是否存在,以及现有测试风格
4. android/ ios/ web/ macos/ windows/ linux/ 中实际启用的目标
5. flutter analyze、flutter test、build 命令是否有记录
最后列出可以安全修改的文件和不应触碰的文件。
范围交给 Claude Code人类需要决定
项目地图文件结构、依赖、测试风格调查可编辑边界
Widget界面部件、无障碍、响应式细节文案和设计判断
state按现有 setStateChangeNotifier、Riverpod 或 Bloc 风格实现全局状态策略
pubspec依赖和资源变更建议是否接受新包
平台Android/iOS/Web/Desktop 差异清单支持目标和商店要求
测试/构建widget test、integration test、命令执行是否合并和发布

谨慎管理 pubspec

pubspec.yaml 控制依赖、资源、SDK 约束和测试包。让 Claude Code 修改它之前,先要求说明原因、替代方案、影响范围和验证命令。

name: cart_ai_demo
description: A small Flutter cart screen used to verify Claude Code prompts.
publish_to: "none"

environment:
  sdk: ">=3.4.0 <4.0.0"

dependencies:
  flutter:
    sdk: flutter

dev_dependencies:
  flutter_test:
    sdk: flutter
  integration_test:
    sdk: flutter
  flutter_lints: ^6.0.0

flutter:
  uses-material-design: true
  assets:
    - assets/images/

新实验可以这样建立基线;已有项目不要机械执行,而是让 Claude Code 对照当前配置提出命令。

flutter create cart_ai_demo
cd cart_ai_demo
flutter pub get
flutter analyze
flutter test

常见坑有三个:assets 缩进错误导致图片找不到;没有看 pubspec.lock 就升级依赖,影响其他页面;为了一个小状态变化引入不必要的状态管理包。安全提示词可以这样写:

检查 pubspec.yaml,判断购物车改动是否真的需要新增依赖。
编辑前请先列出原因、替代方案、受影响文件和验证命令。
未经确认不要修改 pubspec.yaml 或 pubspec.lock。

小步修改 Widget 和 state

下面代码可以放进 flutter create cart_ai_demo 后的 lib/main.dart。它只使用 Flutter SDK。CartController 负责状态变化,Widget 只负责渲染和响应点击。

import 'package:flutter/material.dart';

void main() => runApp(const CartDemoApp());

class CartDemoApp extends StatelessWidget {
  const CartDemoApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Cart AI Demo',
      theme: ThemeData(colorSchemeSeed: Colors.teal, useMaterial3: true),
      home: const CartSummaryPage(),
    );
  }
}

class CartLine {
  const CartLine({required this.name, required this.price, required this.quantity});
  final String name;
  final int price;
  final int quantity;

  CartLine copyWith({int? quantity}) =>
      CartLine(name: name, price: price, quantity: quantity ?? this.quantity);
}

class CartController extends ChangeNotifier {
  final List<CartLine> _lines = const [
    CartLine(name: 'Dart notebook', price: 1800, quantity: 1),
    CartLine(name: 'Flutter sticker', price: 500, quantity: 2),
  ].toList();

  List<CartLine> get lines => List.unmodifiable(_lines);
  int get total => _lines.fold(0, (sum, line) => sum + line.price * line.quantity);

  void increment(int index) {
    final line = _lines[index];
    _lines[index] = line.copyWith(quantity: line.quantity + 1);
    notifyListeners();
  }

  void decrement(int index) {
    final line = _lines[index];
    if (line.quantity == 1) return;
    _lines[index] = line.copyWith(quantity: line.quantity - 1);
    notifyListeners();
  }
}

class CartSummaryPage extends StatefulWidget {
  const CartSummaryPage({super.key});

  @override
  State<CartSummaryPage> createState() => _CartSummaryPageState();
}

class _CartSummaryPageState extends State<CartSummaryPage> {
  late final CartController controller;

  @override
  void initState() {
    super.initState();
    controller = CartController();
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Cart summary')),
      body: AnimatedBuilder(
        animation: controller,
        builder: (context, _) => ListView(
          padding: const EdgeInsets.all(16),
          children: [
            for (final entry in controller.lines.indexed)
              ListTile(
                title: Text(entry.$2.name),
                subtitle: Text('JPY ${entry.$2.price} x ${entry.$2.quantity}'),
                trailing: Wrap(
                  spacing: 8,
                  children: [
                    IconButton(
                      tooltip: 'Decrease ${entry.$2.name}',
                      onPressed: () => controller.decrement(entry.$1),
                      icon: const Icon(Icons.remove_circle_outline),
                    ),
                    IconButton(
                      tooltip: 'Increase ${entry.$2.name}',
                      onPressed: () => controller.increment(entry.$1),
                      icon: const Icon(Icons.add_circle_outline),
                    ),
                  ],
                ),
              ),
            const Divider(),
            Text('Total: JPY ${controller.total}',
                style: Theme.of(context).textTheme.headlineSmall),
          ],
        ),
      ),
    );
  }
}

要明确告诉 Claude Code:不要在 build 中创建 controller;不要把价格计算散落在 Widget 内;不要忘记 dispose;不要为了一个小页面新增包。好的提示词是:

只修改购物车 UI,并把状态变化保持在 CartController 中。
不要在 build 中创建 CartController,不要新增依赖。
请同时添加 widget test,证明点击加号和减号后总价会变化。

测试和设备验证

如果项目名是 cart_ai_demo,下面可以放到 test/cart_summary_test.dart。它验证初始总价、点击加号后的总价和点击减号后的总价。

import 'package:cart_ai_demo/main.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  testWidgets('updates the cart total when quantity changes', (tester) async {
    await tester.pumpWidget(const CartDemoApp());
    expect(find.text('Total: JPY 2800'), findsOneWidget);

    await tester.tap(find.byIcon(Icons.add_circle_outline).first);
    await tester.pump();
    expect(find.text('Total: JPY 4600'), findsOneWidget);

    await tester.tap(find.byIcon(Icons.remove_circle_outline).first);
    await tester.pump();
    expect(find.text('Total: JPY 2800'), findsOneWidget);
  });
}
flutter analyze
flutter test

需要模拟器或真机时,再加 integration test。它更接近用户操作,但运行更慢。

import 'package:cart_ai_demo/main.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';

void main() {
  IntegrationTestWidgetsFlutterBinding.ensureInitialized();

  testWidgets('cart can be changed on a real device', (tester) async {
    await tester.pumpWidget(const CartDemoApp());
    await tester.tap(find.byIcon(Icons.add_circle_outline).last);
    await tester.pumpAndSettle();
    expect(find.text('Total: JPY 3300'), findsOneWidget);
  });
}
flutter devices
flutter test integration_test -d <device_id>

平台差异和构建检查

Flutter 共享 Dart 层,但不共享所有部署规则。Android 可能需要 manifest 权限,iOS 可能需要 Info.plist 文案和签名,Web 可能遇到 CORS 或浏览器 API 限制,桌面端可能需要文件权限或窗口尺寸处理。涉及插件、权限或原生功能时,让 Claude Code 同时检查平台目录。

flutter analyze
flutter test
flutter build apk --debug
flutter build web --release

iOS release 构建需要 macOS 和 Xcode 环境。不要在无法运行 Xcode 的机器上让 Claude Code 声称“iOS 已验证”。提示词里写清楚可执行和不可执行的环境条件。

实际用例至少有四类。第一类是在列表中加入数量、过滤或排序状态;第二类是整理 pubspec.yaml 和 assets;第三类是处理 Android/iOS/Web 单独出现的权限或插件问题;第四类是给没有测试的旧页面补回归测试。每类都要给 Claude Code 目标文件、预期命令、失败时如何报告。

安全提示词和验证记录

调查:读取 lib/、test/、pubspec.yaml 和平台目录,不要编辑,输出项目地图和风险。
实现:只修改 lib/features/cart,遵循现有状态管理,不新增依赖。
pubspec:需要依赖时暂停,先给理由、替代方案、影响范围和验证命令。
验证:添加 widget test,运行 flutter analyze 和 flutter test,并用文件名报告失败。
复查:检查 dispose、异步处理、build 中副作用、平台配置、无障碍、包变更和缺失测试。

Masa 的实务经验是,Flutter 改动最容易出问题的不是 Dart 语法,而是范围太大。先做项目地图,再做小差分,最后用测试和构建确认,结果更容易审核。团队导入时,可以先用免费速查表统一提示词,再用Claude Code 培训与咨询整理团队规则。想进一步设计 AI 工作边界,可以阅读 harness engineering

本文示例按 flutter create cart_ai_demo 的标准结构编写。当前写作环境没有安装 Flutter SDK,因此没有在本机执行 flutter test。发布前请在真实 Flutter 环境中运行 flutter analyzeflutter test 和目标平台构建。Claude Code 能提高速度,但公开质量仍来自范围控制、官方文档确认、测试和真机验证。

#Claude Code #Flutter #Dart #移动开发 #跨平台
免费

免费 PDF: Claude Code 速查表

输入邮箱即可获取一页 PDF,整理常用命令、审查习惯和安全工作流。

我们会妥善保护你的信息,不发送垃圾邮件。

把 Claude Code 变成真正能带来结果的工作流

先领取中文说明的免费 PDF,再进入英文商品页选择合适的教材。如果你需要团队落地、流程设计或内容变现支持,也可以直接咨询。

Masa

关于作者

Masa

专注 Claude Code 实务流程、团队导入和内容转化的工程师。