ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

用AI开发Flutter记账App实战:从踩坑到高效工作流

用AI开发Flutter记账App实战:从踩坑到高效工作流 用 AI 开发 Flutter 记账 App 这件事我前后折腾了大概两周。先说结论AI 确实能干完七八成的活但剩下的两三成才是决定项目能不能上线的关键。这个过程中踩过的坑、试错后沉淀下来的工作流我并不想在博客里复述成那种教程式的体验我更想记录一次真实的、完整的AI辅助开发全流程。1. 为什么我用 AI 也要选记账 App这种老掉牙的项目个人记账 App 在开发者圈子里早就被做烂了但恰恰因为它烂大街才最适合拿来试水 AI 编程。选择这个项目有几个非常现实的原因不是拍脑袋。第一记账 App 涉及的技术栈足够全但复杂度可控。它需要 UI 界面交互、本地 SQLite 数据库存储、状态管理、图表统计如果做得细点还得接入云同步。但每一项单独拎出来都不算难这种广度有、深度浅的项目特性最能暴露 AI 在哪个环节会翻车。第二业务逻辑非常明确、不依赖冷门领域知识。收入支出分类余额这种极简模型的好处是你一眼就能判断 AI 写的代码对不对。换成那种冷门业务领域AI 写错了你根本看不出来那才危险。第三方便验证 AI 代码的边界。我故意选了几个 AI 的老大难环节金额精度处理、跨页状态同步、图表渲染性能、以及数据库版本迁移。这几个点正好是 AI 生成代码容易看起来对其实错的高发区。说白了我不是真缺一个记账 App我看中的是这个项目最容易判断产出质量的特性——在 AI 辅助开发里评估 AI 写的代码到底行不行是核心能力代码本身的炫酷反而不重要。2. 搭环境和初始化的坑最先遭遇的两个 Flutter 报错我一开始图省事直接在 VS Code 里从零建 Flutter 工程结果项目还没跑起来环境先给我上了一课。2.1 VS Code 里那个 visual studio toolchain 报错的前因后果网上很多人问VS Code 跑 Flutter Android 项目报错 unable to find suitable visual studio toolc...我这次也撞上了。我的实际情况和网上大多数帖子不太一样这个报错不是因为你缺 Visual Studio而是因为 Flutter 的 Android 构建链路在探测 Windows 上的 C 工具链时发现了系统里残留的一个不完整的 Visual Studio Build Tools 环境然后编译器探测失败。网上最常见的解法是去装一个完整的 Visual Studio Build Tools但对我这个项目来说那样太重了。我的解决方法是在系统环境变量里把ANDROID_HOME指到了正确的 SDK 位置。检查C:\Program Files (x86)\Microsoft Visual Studio下有没有残留的旧版本目录有的话先备份再重命名移走。在 Flutter 项目根目录运行flutter doctor -v看具体的探测器卡在哪一步。最后发现真正的问题是 Android SDK 里缺了cmake和ndk组件。用 Android Studio 的 SDK Manager 把这两个组件装上这个报错就消失了。这个案例说明一个核心经验AI 能帮你搜索解决方案但它无法感知你本机的具体环境状态环境的排查还得自己来。2.2 apply flutters main gradle plugin imperatively 这种版本升级坑这个报错是典型的升级后遗症报错信息完整版通常是这样的You are applying Flutters main Gradle plugin imperatively using the apply出现这个报错的场景很有代表性通过 AI 辅助生成的工程模板混用了新旧两代 Flutter Gradle Plugin 的配置方式。新版本 Flutter 要求使用plugin管理方式而旧模板还保留着apply plugin:的写死方式。解决思路其实很固定关键是你得知道查哪个文件。需要检查android/settings.gradle和android/app/build.gradle两个文件。AI 生成代码时常常会忽略版本兼容性直接按当前最新版语法生成而实际项目的 Flutter 版本比最新版要旧这时候新旧配置就会打架。如果直接用最新版 Flutter 重建一个干净的工程再把旧代码迁移过去虽然麻烦点但往往能规避一堆版本兼容问题。不值得把时间浪费在无休止的版本匹配上。3. AI 生成的数据库层看似完整实则全是暗雷记账 App 的核心数据层我是让 AI 用sqflite做的本地方案。这一章节我想把 AI 生成代码的表层合理性和底层漏洞完全摊开来讲。3.1 表结构设计的陷阱AI 默认的坏习惯我让 AI 先设计数据库表。第一版它给了三张表一个账户表、一个流水表、一个分类表。单看表结构确实像模像样主键、外键、索引都齐了但这东西经不起细敲CREATE TABLE transactions ( id INTEGER PRIMARY KEY AUTOINCREMENT, amount REAL NOT NULL, category_id INTEGER, note TEXT, date TEXT NOT NULL, type TEXT NOT NULL )第一眼就发现两个问题。金额字段用了REAL浮点数。这是随手写代码的习惯但记账场景对金额精度有硬性要求浮点数的二进制表示可能导致尾差问题。正确做法是金额按分为单位存成整数INTEGER只有展示时才转成元。这是金融类应用的基本原则。AI默认分类表的字段设计也过于理想化没有预留自定义分类的排序字段。用户新建分类后分类列表的展示顺序会变得不可控只能用创建时间排序这很不灵活。这两类问题都属于结构性设计失误不是靠改一行代码能解决的。它们体现的恰恰是当前 AI 编程的最大短板AI 能生成看起来语法正确的代码但缺少对业务领域隐性规则的深层理解。3.2 本地数据库和后端同步AI 建议的架构是一把双刃剑我原本没打算做后端同步但 AI 主动建议我加一层 repository pattern 做数据源抽象方便以后从本地数据库平滑迁移到本地云端同步架构。这个建议本身很专业但我判断它是过度设计。对于一个纯本地优先的记账工具引入 Repository 层确实让数据流更清晰但代价是代码量直接翻倍而且对 AI 来说代码量越大出错的概率和排查难度也越高。最后我的取舍方案是暂时不引入 Repository直接让页面层调用数据库服务。但我在数据库服务类里把接口设计得足够薄比如只封装insertTransaction、queryMonthlySummary这种粗粒度方法将来真要做同步只需要在这层加逻辑就行不需要改动页面。3.3 事务和并发AI 容易忽略的两个核心点AI 生成的第一版数据库操作里批量插入数据没有包在事务里。SQLite 的批量插入如果每条都是独立事务性能会差很多。记账 App 虽然单次插入量不大但历史数据导入场景下问题就大了。更重要的是并发读写场景。AI 生成的代码里所有数据库操作都直接跑在 UI 线程上。SQLite 虽然本身支持多线程访问但sqflite默认是单实例的如果 UI 线程和后台线程同时访问会因为操作排队而卡住 UI。这种问题的典型表现是页面切换时有明显卡顿甚至 ANR。但 AI 在静态代码里根本发现不了这种性能隐患因为它不会真跑到真机上去感受流畅度。这类问题只能靠人肉真机验证。4. AI 写 UI 代码的真实水平快是真快散装也是真散装记账 App 的 UI 部分我让 AI 分别用两个方案各生成了一版一版是传统的StatefulWidget写法另一版是Riverpod状态管理方案。这部分的经验非常说明问题。4.1 生成页面的快和碎其实是同一个原因AI 生成页面的速度确实令人惊叹。我说帮我生成一个账单列表页包含日期分组、金额显示、左滑删除它一分钟内就给了一个完整页面而且布局基本符合需求。但当你开始在此基础上叠加功能时问题就来了。比如要在页面里加个月度汇总卡片AI 给出的做法是直接改build方法往里嵌套一个新的Widget。第一次改动没问题。第二次、第三次叠加后build方法膨胀成了四五百行里面各种if判断、嵌套三元表达式可读性急剧下降。根本原因在于AI 没有长期代码维护的概念。它擅长单次生成但重构意识几乎没有。我的对策是每让 AI 改一次就手动做一些整理动作把回调函数抽出去、把大Widget拆成独立组件、把硬编码的颜色和间距提取成常量。本质上我成了它的代码清洁工。4.2 使用 Riverpod 冷热状态管理时花了多长时间才摸清它的逻辑后面我换用 Riverpod 重构计数和账户总览部分。这个过程中对 AI 的逻辑能力有了更清晰的认识。Riverpod 的状态更新逻辑比setState复杂得多涉及Provider的监听、自动失效、异步加载等机制。AI 经常把StateProvider和FutureProvider的职责搞混导致我明明改了分类数据界面上的支出统计却不刷新。最有意思的一次它给的代码里同时出现了两个Provider监听同一个模型的小状态相当于你给别人同时发了两个遥控器控制同一台电视必然导致状态交互打架。这种设计问题靠 AI 自己是查不出来的必须你理解状态管理机制之后才能从代码草堆里挑出那根针来。4.3 AI 选图表库的顺手牵羊问题我让 AI 推荐图表库它推荐了fl_chart。这个选择本身没问题但我发现它写图表配置代码时有个让人头疼的习惯在代码里硬编码了一堆自己编造的配置项。比如它写了一行FlTitlesData(bottomTitles: AxisTitles(...))但当时的版本里根本没有这个 API编译直接报错。这不是它笨是因为它的训练数据里混入了不同版本的 API 用法它无法判断当前项目依赖的版本具体是哪个。后续图表配置我就自己直接对着fl_chart官方的 API 文档手写AI 只用来生成数据结构转换的胶水代码。项目到了这个阶段我已经不再把 AI 当主力开发者而是当一个熟悉套路但容易记混 API 的初级助手用。5. 接入 AI 能力账目自动分类的实现和它的实际价值说完了 AI 写代码的问题这个项目里真正让记账 App 显得智能的部分是把大模型接进来做自动分类。这一章我来把实现细节和效果边界拆清楚。5.1 方案对比本地模型还是 API 调用通用的做法有两种设备端跑个小模型或者调云端大模型 API。我选择了后者原因是设备端部署对内存的消耗非常明显而且初始化和首次推理的耗时较长。记账分类不是高频操作把这种低频但高价值的任务丢给云端是合理的。核心思路很简单当用户录入一笔新账单时如果用户没有手动选择分类App 把这笔账单的金额商家/描述类型发给大模型返回适合的分类。建议在正式开发前直接测试 Prompt 的稳定性。比如给模型发送你是一个个人记账助手。请把这条消费记录归入指定分类体系中只回复分类名称。 记录在全家便利店购买了关东煮、饭团和豆浆共消费18.5元。 分类选项餐饮、交通、购物、居住、娱乐、医疗、教育、其他。5.2 Prompt 要细节到什么程度第一版 Prompt 非常简陋直接让模型帮忙把这个账单分类结果它有几种相当随意的发挥有时候回复便利店有时候回复食品甚至带上了多余的解释文字。对 App 来说这些输出是没法直接用的。第二次迭代我加了两种约束一是强约束输出格式只允许回复给定的分类名称二是把金额级别加入判断逻辑——比如一笔 18.5 元的便利店消费应该归为餐饮但如果金额变成 180 元就可能是购物。加了这些约束后效果立刻好了很多。但我必须说一个现实问题即便加了约束模型的分类依然存在一定概率的合理但是错——它在语义上是合理的但不符合用户的实际记账习惯。比如买书这件事有人算教育有人算娱乐有人算文化消费。所以设计上必须允许用户手动改分类。5.3 离线兜底没网的时候怎么办这是我在产品层面踩出的一个经验。AI 自动分类如果做成强依赖一旦断网用户就连记账都记不了这违背了记账工具的底线。最终的做法是三层兜底逻辑第一层本地基于描述关键词的规则匹配比如描述里含加油站石油自动归类到交通第二层匹配不到关键词时才走云端大模型第三层云端请求超时或失败时默认归到其他提醒用户稍后手动分类不影响记账主流程。这样保证了断网状态下记账主流程完全通畅AI 分类只是一个增强功能而不是一个前置依赖。这也是个人记账AI组合最合理的产品定位。6. 性能优化与包体积控制AI 不会替你思考的事这一章聊聊那些 AI 代码里看不见的性能坑以及我实际动手优化的部分。6.1 列表卡顿优化flutter isolate 的用武之地记账 App 的月度账单列表如果一个月有几百上千条记录按照 AI 给的默认写法从数据库查询后直接列表渲染在低端 Android 机上会出现明显的滚动掉帧。主要原因有两点一是数据解析把数据库行映射成 Dart 对象过程在 UI 线程执行二是列表项构建时重复计算了一些耗时逻辑。AI 的解决方案和我的方案在优化方向上是一致的用Isolate把数据解析挪到后台线程。但 AI 给的具体方案第一次运行时直接把 App 干崩溃了——它用了一个已经被废弃的 API新版本 Flutter 中行为完全变了。我自己重写后才理顺正确的做法数据量小少于 300 条直接解析不用 Isolatecompute函数的创建开销比省下来的还大。数据量大500 条以上用compute把原始行的Map列表传给后台 Isolate解析成模型对象后再回传。列表项组件做轻量化const构造、按需渲染不可见区域。这个优化做完列表滚动明显顺滑了。6.2 让 AI 帮忙做内存优化它给的代码看着很有道理我让 AI分析并优化内存使用它找出了两个潜在泄漏点一个是在dispose中未释放AnimationController另一个是全局静态持有BuildContext的引用。这两点判断都是对的。但它给出的修复方案里竟然引入了新的问题它在某些不需要dispose的StatelessWidget里写了dispose方法这属于凭空创造不存在的生命周期。直接把这个方案丢掉了。这个经历很像让 AI 开排查报告可以让它直接动手术还要多留个心眼。6.3 release 包体积与启动优化个人记账 App 根本不应该超过 30MB。AI 默认引入了一堆依赖后release 包体积直接到了 45MB。精简主要从三方面入手移除重复功能的库比如同时存在两个 JSON 解析库只留一个对所有图片资源做压缩和 WebP 转换开启 Flutter 的--split-debug-info和--obfuscate。包体积最终降到 25MB 左右。这类优化工作靠 AI 没法完成因为它总是倾向于加库而不是减库你得有意识地反向控制。7. 完整心流复盘AI 辅助编程的高效工作流最后把两周的实践总结成一套我自己现在还在用的工作流。这套流程不是什么行业标准就是踩出来的经验。7.1 什么活儿应该交给 AI什么活儿必须自己干项目环节AI 干活效率人必须干的活我的心得搭页面/UI 组件极高梳理交互逻辑、控制页面复杂度先给 AI 定好 Widget 拆分规则再让它写数据库 CRUD高但结构会散自己定表结构、事务边界表结构只能自己设计AI 写预编译 SQL状态管理中容易缝合怪理清状态流向和使用场景让 AI 只写单个 Provider 逻辑串联自己来网络层封装高而且模板化严重订好错误码规范和重试策略AI 生成的网络层适合参考不适合直接用性能分析低必须真机体验工具实测AI 只能做常见问题检查测不出来真实体验调试低自己看调用栈搞清楚逻辑比让 AI 猜快得多7.2 提示词怎么写最有效这一步对 AI 编程的产出质量影响比我预想的大得多。同样是让 AI 写代码用这套模板的产出质量明显更高背景先行一句话说清楚项目是什么。不建议直接丢一句帮我写一个记账 App 账单页。我会提供具体上下文比如 项目是一个本地优先的个人记账应用使用 Flutter 3.xx sqflite Riverpod业务场景是用户查看当月账单流水。给代码约束说明不能用什么、必须遵守什么。比如金额一律用整数分存储UI 层再转元效果立竿见影。要求它先给方案再写代码我发现让 AI先列出实现计划和可能的风险点再输出代码生成的代码质量会更高。让它养成先思考后动手的习惯很重要。一次只让它改一个点这个经验反复验证过让 AI 同时改三处逻辑它大概率会改坏其中一处。7.3 值得一比的第二个程序员定位如果把 AI 当成资深程序员来用处处都会觉得它不够格。但如果当成一个记忆力超强但理解力有限的新人而且是一个喜欢动手不喜欢动脑的新人用起来就顺手得多。我这次的体会是你的水平决定了 AI 的产出质量。你对架构设计、数据精度、并发安全、状态管理这些基础问题理解得越深AI 越能成为你的加速器。反之如果你完全不懂代码把整个项目丢给 AI 让它独立开发大概率会得到一个看起来是那么回事、但改了这头塌了那头的工程。最终我做出来的记账 App 能用、能同步、能自动分类不是因为我比 AI 聪明而是因为我清楚地知道哪些地方必须自己牢牢把住方向盘——数据库结构、状态流向、同步策略、并发和精度——其余那些流程化、重复性的编码工作尽管放心交给 AI 去跑。
返回列表