用 AI 写 Android 需求:少踩坑的实战心得

100 阅读11分钟

先说结论

用 AI 写 Android 代码这事,我折腾了一段时间,最大的感受就是——AI 写出来的代码质量,八成取决于你怎么"喂"它

很多人第一次用的时候都会觉得"哇好厉害",第二次就开始骂"这写的什么玩意"。其实不是 AI 变笨了,是你第一次恰好问了一个它训练数据里烂大街的问题(比如写个 RecyclerView adapter),第二次碰到了你项目里特有的逻辑,它就开始胡编了。

所以这篇文章不是教你怎么用 AI 工具,而是聊聊怎么才能让 AI 生成的代码真正能用,而不是看着像那么回事、一跑就崩。重点会介绍我们团队实际在用的两个"大杀器":Spec 驱动开发Skills 技能体系


一、最重要的一件事:让 AI 知道你的项目长什么样

这一点怎么强调都不过分。

你想想,你让一个刚入职的校招生写代码,你不给他看项目代码、不告诉他架构分层、不说命名规范,他写出来的东西能直接用吗?AI 也一样,甚至比校招生更需要这些信息——因为校招生好歹会自己翻翻项目,AI 不会,你不喂它就真的不知道。

具体怎么做:

把你项目中已有的同类代码直接贴给它当范例。比如要新写一个 Service,就把已有的 DepartmentService.java 丢给它,跟它说"照着这个风格来"。这比你用文字描述半天架构有用得多。

再比如我们项目里日志统一用 WwLog.i(TAG, msg),你不说的话 AI 百分百给你写成 Log.d("tag", "xxx")——它又不知道你项目里有自己的日志工具。

但问题来了——每次都手动喂这些上下文,太累了。一个需求改三天,你每天开新对话都得重新交代一遍项目背景?这就引出了我们真正的解法。


二、Spec:把需求变成 AI 能精确执行的"施工图纸"

为什么要写 Spec

我以前犯过一个经典错误:需求评审完,直接把 PRD 里一整段功能描述丢给 AI,让它"帮我实现一下"。结果它确实洋洋洒洒给我生成了好几个文件,但代码之间的调用关系是乱的,数据模型和后端接口也对不上,基本等于白写。

后来我们团队搞了一套 Spec 驱动开发 的流程,效果立竿见影。

所谓 Spec,不是 PRD,也不是技术方案文档,而是一份面向 AI 的、结构化的功能规格说明。 它的核心目的是:把你脑子里"想清楚了但没写下来"的东西,用 AI 能精准理解的格式表达出来。

Spec 长什么样

一份好的 Spec 包含三个核心部分:

1. 功能概述:功能点列表 + 用户流程图

不是写散文,而是用编号表格 + Mermaid 流程图。比如做一个"会议预约"功能:

| 编号 | 功能 | 描述 |
|------|------|------|
| F1 | 创建会议 | 填写标题、时间、参与人,发起预约 |
| F2 | 会议列表 | 展示我参与的所有会议,支持按时间筛选 |
| F3 | 会议详情 | 查看会议信息,支持修改和取消 |

再配一个流程图,AI 就能准确理解页面之间的跳转关系和分支逻辑。你不画这个图,AI 就会按它自己的理解来猜——猜错了你还得花时间改。

2. 数据结构定义:直接贴 Protobuf

这个太关键了。与其用自然语言描述"会议信息包含标题、时间、参与人列表",不如直接把 proto 文件贴上来:

message MeetingInfo {
    optional string title = 1;       // 会议标题
    optional uint64 start_time = 2;  // 开始时间戳
    optional uint64 end_time = 3;    // 结束时间戳
    repeated uint64 participants = 4; // 参与人 VID 列表
}

字段类型、可空性、列表还是单值,一目了然。AI 拿到这个生成的数据模型基本不会出错。

3. API 接口规范:接口列表 + 时序图

把客户端和服务端的交互用时序图画出来,AI 就知道该在什么时机调什么接口、回调怎么处理。

用 AI 生成 Spec

有意思的是,Spec 本身也可以让 AI 来帮你生成。我们做了一个 spec-create 的 Skill(后面会详细讲 Skill 是什么),你只需要给出需求描述和相关 proto 文件,它就会自动收集信息、和你确认模糊的地方、然后按标准模板生成一份完整的 Spec 文档。

这个流程的好处是双向的:一方面 AI 帮你把需求结构化了,另一方面你在确认 Spec 的过程中,也把技术方案想清楚了。好几次我在审 AI 生成的 Spec 时才发现,"哦这里有个边界情况我没考虑到"。


三、Skills:把项目经验固化成 AI 的"技能包"

为什么需要 Skills

上面说了要给 AI 喂上下文——项目架构、编码规范、历史坑点。但每次手动喂太累了,而且容易遗漏。

Skill 就是把这些零散的项目经验打包成一个结构化的"技能包",AI 在需要的时候自动加载。 你可以理解为:给 AI 装了一个"项目老员工的脑子"。

我们实际在用的 Skills

说几个我们团队 Android 端实际在用的 Skill,你感受一下这个东西的威力:

1. jni-interface:JNI 接口生成

我们项目有大量 C++ 和 Java 的 JNI 调用。手写 JNI 桥接代码是一件又臭又长又容易出错的事——参数类型映射、异常处理、线程切换,每一步都可能写错。

这个 Skill 里内置了完整的类型映射规则、代码模板和项目特有的 JNI 封装方式。AI 加载这个 Skill 后,你只需要给它 C++ 的接口签名,它就能自动生成对应的 Java Service 接口 + native 方法 + JNI 实现。以前一个接口要写半小时反复调试,现在基本一次生成就能用。

2. codecc-fixer:代码缺陷自动修复

这个 Skill 直接对接 CodeCC 代码检查平台,自动拉取缺陷列表(空指针风险、资源未关闭、Late Init 问题等),然后按照预定义的修复规则逐个修复。相当于把 lint 修复这个重复劳动完全自动化了。

3. auto-jni-generator:JNI 变更自动感知

更进一步,这个 Skill 能自动检测 *_service.hpp 文件的变更,然后自动触发 JNI 接口代码的重新生成。相当于 C++ 接口一改,Java 侧的代码自动跟上。

怎么做一个好的 Skill

写了这么多 Skill 之后,我总结出几个关键点:

第一,Skill 里一定要有 references(参考资料)。 光写"遵循项目规范"没用,你得把规范文档、代码模板、类型映射表这些实实在在的材料放进去。AI 不是靠"理解原则"干活的,它靠的是"看到具体范例然后模仿"。

第二,Skill 的粒度要合适。 一个 Skill 做一件事。不要搞一个"全能开发助手"的 Skill,那和没有 Skill 效果差不多。我们的 Skill 都是按场景划分的:JNI 生成是一个、代码同步是一个、缺陷修复是一个,互不干扰。

第三,Skill 里要写清楚触发条件和工作流程。 告诉 AI"你拿到什么输入"、"按什么步骤执行"、"最终输出什么"。越明确,AI 越不会跑偏。


四、完整的工作流:Spec + Skills + Agents 的协作

有了 Spec 和 Skills,我们团队的开发流程变成了这样:

拿到需求
  ↓
用 spec-create Skill 生成 Spec 文档
  ↓
人工审核 Spec(确认功能点、接口、数据结构)
  ↓
AI 按 Spec 拆分任务:Service 层 → UI 层
  ↓
Service 开发:加载 jni-interface / dev-guideSkill,按 Spec 实现
  ↓
UI 开发:加载 ui-guide Skill + Figma 设计稿,按 Spec 实现
  ↓
自动编译验证
  ↓
AI Code Review(逻辑审查 + 规范审查)
  ↓
人工终审业务逻辑
  ↓
提交

有的团队甚至做得更彻底——他们搞了一套 Agent 协作机制:用一个 feature Command 启动整个流程,AI 充当 Project Manager 角色,按顺序调度 service-developer Agent 和 ui-developer Agent 完成开发,最后调度 spec-reviewer Agent 做 Code Review。开发者全程只需要在关键节点做确认。

这套流程的核心理念是:人负责"想清楚要什么"(Spec),AI 负责"把它实现出来"(Skills + Agents)。


五、Android 的坑,你不提 AI 是真的不会注意

不管你 Spec 写得多好、Skill 做得多全,有些 Android 特有的坑还是需要你主动防范。这些可以写进项目的 Rules(全局规则)里,AI 每次生成代码时自动遵循:

生命周期问题:AI 经常在回调里直接更新 UI,完全不管 Activity 是不是已经被回收了。我之前让它写的一个网络回调,线上直接崩了一片。现在我们的 Rules 里明确写了"异步回调必须检查生命周期状态"。

线程问题:AI 生成的代码有时候会把网络请求写在主线程,有时候在子线程里直接操作 View。Rules 里写死"网络请求走 IO 线程,UI 更新切回主线程"。

RecyclerView 复用:AI 写 onBindViewHolder 的时候,很喜欢只设置"有值"的情况,不处理"没值"的情况。Rules 里加了"onBindViewHolder 中必须重置所有控件状态"。

这些 Rules 的好处是一次配置,永久生效。不用每次开新对话都交代一遍"记得处理生命周期啊"。


六、一个容易被忽视的大杀器:让 AI 反过来审查代码

代码写完之后不要急着提交。我们做了两个 Review 相关的 Skill:

  • 逻辑审查logic-reviewer):专抓严重问题——内存泄漏、线程安全、Crash 风险、资源泄漏、循环边界错误、RecyclerView 复用状态泄漏。并且内置了"误报避免规则",比如我们的 Service 回调默认在主线程,不需要额外切线程,这种就不会被误报。

  • 规范审查spec-reviewer):检查代码是否符合团队编码规范——国际化文案有没有提取、UI 组件有没有用标准的、颜色字体有没有走主题。

实际操作下来,这两轮 AI Review 能发现大概 30% 的问题。有点像自己写完文章再通读一遍——写的时候沉浸在逻辑里容易忽略细节,换个视角就能看到。

当然 AI 审查也不是万能的,业务逻辑对不对这事还是得你自己把关。AI 能帮你抓空指针、抓线程问题、抓资源泄漏,但它判断不了"这个场景下到底应该弹 Toast 还是弹 Dialog"。


七、总结:从"手写代码"到"经营 AI 的知识体系"

用 AI 开发到现在,我最大的感受是——工作重心发生了转移

以前是:需求评审 → 想技术方案 → 写代码 → 调试 → 提交。80% 的时间花在"写"和"调"上。

现在是:需求评审 → 写 Spec → 审 Spec → AI 生成代码 → 验证 → AI Review → 人工终审。"写"的时间大幅压缩,但"想清楚"和"验证"的时间没变甚至增加了

总体效率提升大概在 30%~50%,主要看需求的复杂度——越是模式化的代码(CRUD、列表页、JNI 桥接、代码同步),AI 的加速效果越明显;越是涉及复杂业务逻辑和边界条件的,人工介入越多。

最后用一张表总结核心方法论:

层次工具解决什么问题
Specspec-create Skill把模糊的需求变成 AI 能精确执行的结构化规格
Skills项目特有技能包把零散的项目经验固化为 AI 可复用的知识
Rules项目全局规则编码规范、常见坑点,一次配置永久生效
Agents专职开发角色Service 开发、UI 开发、Code Review 各司其职
Commands一键工作流串联 Spec → 开发 → 编译 → Review 全流程

说白了,用好 AI 的关键不是学会什么高级 prompt 技巧,而是把你团队的项目知识体系经营好——Spec 是需求知识,Skill 是开发知识,Rule 是规范知识。这些东西整理得越好,AI 就越像一个"真正懂你项目的队友",而不是一个"什么都会一点但什么都不深入的外包"。

这个过程本身,其实也在倒逼团队把很多"口口相传"的隐性知识显性化——这算是一个意外但很有价值的收获。