AI 写代码越来越猛,Android 开发会被取代吗
AI 写代码越来越猛,Android 开发会被取代吗
Cursor 的 Tab 键正在吃掉什么
去年冬天我试 Cursor 的时候,它补全一个 RecyclerView.Adapter 还磕磕绊绊,ViewHolder 的泛型经常写错,onBindViewHolder 里给我塞一堆没定义的变量。今年三月再打开,同一个项目同一个文件,Tab 键按下去,整段 DiffUtil 的 areContentsTheSame 逻辑直接蹦出来,连 payload 的部分更新都帮我考虑到了。我盯着屏幕愣了两秒,不是因为惊艳,是因为我突然意识到自己已经习惯了这种"愣两秒"的感觉——从 GitHub Copilot 到 Cursor 再到 Gemini Code Assist,这个愣神的间隔越来越短,短到快要消失。
Android 开发的特殊性在于,我们面对的不是干净的算法题,而是一整套充满历史包袱的生态系统。Activity 生命周期、Fragment 的 commit 规则、Service 的启动限制、BroadcastReceiver 的声明要求,这些知识散布在二十多年的 API 沉积层里,彼此牵制,牵一发而动全身。AI 现在能写出看起来对的代码,但它对"看起来对"和"运行时对"之间的鸿沟,理解得还不够深。
我做过一个故意的测试。让 Cursor 写一个 Android 14(API 34)上的前台服务,要求带类型声明(foregroundServiceType)和运行时权限申请(POST_NOTIFICATIONS + FOREGROUND_SERVICE_MEDIA_PLAYBACK)。它生成的代码在语法上毫无问题,AndroidManifest.xml 里也填了正确的属性。但跑起来就崩溃——它把 Service 的 startForeground 调用放在了 onCreate 里,而 Android 14 要求这个调用必须在 Service 启动后的五秒内完成,且必须在正确的生命周期回调中。更隐蔽的是,它没处理用户拒绝通知权限后的降级逻辑,这在 Android 13+ 上是必现的崩溃路径。AI 学的是 GitHub 上大量的历史代码,而历史代码里充斥着 pre-Android 13 的写法,那些 repo 的 star 数可能还很高,但已经不能照搬到新项目里了。
这不是 AI 的错,是训练数据的时效性问题。但这个问题对 Android 开发尤其致命,因为 Google 每年都在收紧权限和行为限制,Android 10 的分区存储、11 的包可见性、12 的 SplashScreen 和近似位置、13 的通知权限和主题图标、14 的更严格前台服务、15 的私密空间和屏幕录制检测——每一年的 targetSdkVersion 升级都是一次考古和重构。AI 的代码生成基于概率,而 Android 的兼容性要求基于精确的政策时间表,这两者之间存在结构性错位。
Jetpack Compose 是试金石
Compose 可能是检验 AI 代码生成能力的最佳场景。它的声明式语法表面看起来简洁,实际写起来到处是坑。remember 和 rememberSaveable 的区别、derivedStateOf 的使用时机、LaunchedEffect 的 key 选择、Modifier 链的执行顺序、自定义 Layout 的 Intrinsic 测量——这些概念在官方文档里都有,但文档不会告诉你"什么时候会掉进坑里"。
我让几个不同的 AI 工具实现一个常见的需求:带粘性头部的分组列表(类似微信通讯录的字母分组),要求支持展开收起、流畅的滚动定位、以及分组变化时的动画。Cursor 给出的第一版用了 LazyColumn 加 stickyHeader,看起来标准,但展开收起时头部闪烁,因为 remember 的状态在重组时没有正确处理 key 的变化。Copilot 的版本试图用 AnimatedVisibility,但把 enter/exit 动画和 LazyColumn 的 item 动画混在一起,导致测量冲突,Compose 直接抛 IllegalStateException。Gemini 的版本最保守,干脆不用动画,但也没处理分组数据变化时列表位置的保持,展开一个分组后用户视角会乱跳。
我最后自己写的版本用了 MutableInteractionSource 跟踪交互状态,在 derivedStateOf 里计算展开后的可见项集合,用 animateItemPlacement 处理位置变化,并且给每个分组头部加了独立的 LaunchedEffect 来处理延迟加载的副作用。整个实现不到两百行,但 AI 没有一个版本能在三次迭代内把这些问题全部解决。它们每次都能修掉我指出的具体 bug,但引入新的问题,像打地鼠一样。
这说明什么?Compose 的编程模型需要理解"重组"这个核心机制,而重组是声明式 UI 框架特有的概念,和传统命令式 UI 的思维方式完全不同。AI 见过大量 Compose 代码,但它对"为什么这样写"的理解是浅层的。它能匹配模式,但难以推断模式背后的设计意图。当需求稍微偏离常见路径——比如要在粘性头部里嵌套一个横向滚动的子列表——AI 就开始胡编乱造,生成根本不存在的方法调用,或者把 Modifier 传进不该传的地方。
Google 自己在 I/O 2024 上推的 Studio Bot 更说明问题。这个内置在 Android Studio 里的 Gemini 助手,回答 Compose 相关问题的准确率,据我自己测试和 Reddit 上的开发者反馈,大概在六成左右。问它 "为什么 Modifier.pointerInput 在重组后丢失状态",它会给出一堆关于 remember 的通用解释,但触不到真正的问题:pointerInput 的 key 变化会导致底层协程作用域重启。这个细节在官方文档里其实有写,但藏得很深,AI 显然没有把这个知识点和常见问题建立有效关联。
Kotlin 协程和 "看起来能跑"
Android 开发里另一个 AI 重灾区是异步编程。Kotlin 协程从 2017 年推出到现在,坑一点没少。lifecycleScope 和 viewModelScope 的区别、Dispatchers.Default 和 IO 的适用场景、withContext 的异常传播、Flow 的冷流热流转换、SharedIn 的 started 参数选择——这些决策点需要理解并发模型和业务场景的双重上下文。
AI 生成的协程代码有一个通病:滥用 GlobalScope。这个在官方文档里明确标记为"高级 API,强烈不建议应用代码使用"的东西,在 AI 的输出里频繁出现,因为训练数据里大量老旧代码和 StackOverflow 答案还在用它。更隐蔽的是,AI 喜欢把 suspend 函数和回调式 API 混着用,生成出来的代码"能跑",但取消逻辑一团糟。比如一个网络请求用 Retrofit 的 suspend 接口,但外层套了个 CoroutineExceptionHandler,同时又在 ViewModel 的 onCleared 里手动取消 Job——这三个机制互相覆盖,实际异常处理和生命周期管理完全是乱的。
我在一个真实项目里见过 AI 生成的"数据层"代码:Room 的查询返回 Flow,在 Repository 里用 flowOn(Dispatchers.IO) 切换调度器,然后 ViewModel 里用 launchIn(viewModelScope) 收集,UI 层又用 collectAsState 转成 Compose 的状态。这条链表面上每个环节都用了"正确"的 API,但 Room 的 Flow 已经是主线程安全的(Kotlin 协程的 Room 集成会自动处理调度),flowOn(IO) 是多此一举,而且破坏了事务性操作的线程约束。更麻烦的是,collectAsState 在 Compose 里默认用 Dispatchers.Main.immediate,和 flowOn 的切换形成不必要的线程跳跃,复杂列表滚动时会有可感知的卡顿。这些性能问题不会崩溃,不会报错,就是慢,就是不顺滑——而 AI 对这种"死亡 by a thousand cuts"完全没有概念。
Google 在 Kotlin 协程官方文档里花了很大篇幅讲结构化并发,但 AI 似乎学进去了"语法"没学进去"结构"。它知道 withContext 怎么写,但不知道什么情况下一个 CoroutineScope 应该属于谁、生命周期怎么绑定、异常怎么向上冒泡。这在 Android 这种生命周期复杂的平台上,后果就是内存泄漏和不可预期的崩溃。LeakCanary 抓到的泄漏链里,Activity 被某个挂起的协程持有,这种 case 我调试过不下十次,源头往往是 AI 生成的一段"简洁"的异步代码。
构建系统和工程化:AI 的盲区
如果说代码生成是 AI 的舒适区,那 Android 的构建系统就是它的盲区,而且是越来越深的盲区。Gradle + AGP(Android Gradle Plugin)的组合,版本兼容性矩阵复杂到 Google 自己都要出对照表。AGP 8.0 强制要求 JDK 17、R8 的完整模式、非传递性 R 类、namespace 替代 applicationId 在构建配置里的位置——这些 breaking changes 不是 AI 能自动帮你迁移的。
我试过让 Cursor 把一个 AGP 7.4 的项目升到 8.2。它改了 gradle 文件里的版本号,调整了 namespace 语法,甚至知道要加 buildConfig 的显式启用标志。但跑起来各种报错:某个第三方库用了被移除的 Transform API,某个 Gradle 插件的版本不兼容新的配置缓存,某个自定义的 task 类型签名变了。AI 每次都能根据错误日志给出一个"修复",但往往是头痛医头,修复一个引出下一个,像剥洋葱一样。最后我花了整整一个下午手动处理,比不用 AI 自己看 migration guide 可能还慢,因为中间多了很多无效的来回。
更深层的问题是,Android 的构建优化本身就是专业领域。Build cache、配置缓存、非传递性 R 类、资源 shrinker、Dex 合并策略、App bundle 的动态功能模块拆分——这些决策影响的是团队的构建速度和发布效率,不是单个功能能不能跑。AI 可以生成"能编译"的 build.gradle,但生成不了"工程上合理"的构建策略。我见过 AI 给的建议是关掉 R8 的代码缩减来"解决"某个混淆问题,这在生产环境完全是自杀行为;也见过它建议把 minSdk 从 24 降到 21 来兼容某个老库,完全不顾 Android 5.0 上的运行时权限和通知渠道缺失。
JetBrains 的 Amper 项目(虽然还在早期)和 Google 对 Bazel 的持续投入,某种程度上都是对 Gradle 复杂性的回应。但 AI 在这些新工具上的训练数据更少,表现更差。我试过早期的 Amper 配置,AI 几乎帮不上忙,因为样本太少。这形成了一个悖论:越是新的、试图简化问题的工具,AI 越难发挥作用;越是老的、积累大量历史债务的系统,AI 越容易生成"看起来对"但实际有隐患的代码。
低代码平台和 AI 的合谋
市面上开始出现一些"AI 生成完整 Android 应用"的产品,比如基于 FlutterFlow、Adalo 或者更专门的 Mobile AI builder。这些平台本质上是在低代码的框架上加了一层自然语言接口,让 AI 生成的是"配置"而不是"代码"。对简单应用——信息展示、表单提交、列表浏览——这确实能工作,而且可能比找外包更快更便宜。
但这里有个关键的边界问题。这些平台能生成的应用,在 Android 生态里属于"被 Google 允许存在"的最低限度。它们通常用 Flutter 或 React Native 的跨端方案,打包出来的 APK 体积大、启动慢、系统级集成弱。更重要的是,它们处理不了 Android 特有的平台能力:后台定位的权限策略、通知渠道的分组配置、快捷方式的动态更新、App Widget 的远程视图、甚至最基本的 Deep Link 和 App Link 区分——这些都需要精确理解 Android 的意图系统和安全模型。
Google 在 2024 年对 Play Store 的政策收紧,尤其是 AI 生成内容的应用审核,以及后台权限和电池优化的持续限制,实际上抬高了"合规 Android 应用"的门槛。一个靠 AI 低代码平台生成的应用,很可能在审核环节就被打回,或者上线后因为后台行为被系统杀死、被用户投诉耗电。这些不是代码层面的 bug,是平台政策和系统行为的综合结果,需要开发者对 Android 生态有持续跟踪的理解。
我看过一个案例,某团队用 AI 工具生成了一款"智能记账"应用,核心功能是自动读取短信和通知来识别消费记录。在 Android 13 之前这能跑,靠 NotificationListenerService 实现。Android 13 开始,这个服务需要用户每次都在设置里手动启用,且 Google 对"读取通知"的权限审核极度严格,非核心功能基本不给过。Android 14 更进一步,后台启动的 Service 受到前台服务类型的严格限制。这个团队的应用实际上已经死了,但他们直到用户投诉收不到自动记录时才发现问题——AI 生成代码的时候不会告诉你这些政策变化,它甚至不知道你准备把应用发到哪个市场、面向哪个 Android 版本分布。
被低估的:调试和诊断能力
Android 开发里有一个大块的隐性工作,是调试。不是写代码,是搞清楚为什么代码不工作。ANR 的主线程阻塞分析、Native crash 的 tombstone 解读、内存泄漏的 hprof 剖析、卡顿的 systrace 追踪、Jetpack Compose 的重组计数和跳过分析——这些诊断工作需要的不是语法知识,是对系统行为的深层理解和经验直觉。
AI 在调试辅助上有所进步。Cursor 可以帮你读 crash log,定位到大概的代码位置;Google 的 Studio Bot 能解释某些 ANR 的常见原因。但实际的复杂问题往往是多因素交织。我曾经花两天追踪一个只在三星 One UI 5.1 上出现的 Fragment 状态丢失问题,最终发现是厂商对 activity 重建的定制化行为和一个第三方库的反射调用相互作用。这种调试过程需要查阅厂商文档、分析系统源码差异、构造最小复现、逐步剥离变量——AI 完全无法替代,因为它没有"怀疑某个特定厂商定制化"的经验模型,也无法执行实际的设备测试和验证。
Firebase Crashlytics 的数据里,大量崩溃是设备特异的。某款芯片的 GPU 驱动对特定纹理格式支持不完整,某个 OEM 的电池优化策略杀死了预期的后台定时任务,某个地区运营商的网络配置导致 TLS 握手异常——这些知识分散在 Google Issue Tracker、厂商开发者论坛、XDA 的逆向分析帖里,没有结构化的训练数据。AI 可以告诉你 "NullPointerException 通常是因为对象未初始化",但它无法告诉你 "这个 NPE 只发生在小米 MIUI 14 的夜间模式切换时,因为系统资源回收的一个 race condition"。
那么,什么会被取代
说这么多 AI 的不足,不是为了唱反调。AI 确实在快速吃掉 Android 开发的某些层面。我认为最危险的是"样板代码"的编写者——那些主要工作是拼接 RecyclerView、写 Retrofit 接口定义、配 Dagger/Hilt 模块、搭 MVVM 脚手架的开发者。这些工作的模式足够固定,上下文足够有限,AI 的学习曲线正在迅速覆盖。
2023 年 Stack Overflow 的开发者调查里,Android 开发者报告使用 AI 工具的比例已经高于后端开发者。今年我身边的情况更极端:几个中型团队里,初级开发的 PR 已经有明显 AI 生成的痕迹,代码风格忽好忽坏,注释和实现偶尔对不上(AI 喜欢保留它最初生成的注释,即使代码已经改过)。Code review 的人需要额外花精力识别这些"AI 幻觉"——某个方法名看起来合理但库里不存在,某个常量引用在编译时才发现拼错了一个字母。
Google 自己的动作也值得注意。Android Studio Iguana 和 Jellyfish 版本里,Studio Bot 的集成越来越深,从代码补全扩展到错误解释、测试生成、甚至文档查询。JetBrains 的 AI Assistant 在 Kotlin 支持上投入巨大,因为 Kotlin 的语法特性(扩展函数、DSL、协程)对 AI 的训练来说比 Java 更有挑战性,但也更有价值。这些官方工具的成熟,会进一步压缩"纯编码"工作的价值空间。
但我观察到一个反向趋势:一些团队开始设立"AI 输出审核"的角色,或者要求资深开发花更多时间在架构约束和代码规范上,确保 AI 生成的代码不偏离项目的技术方向。这有点像当年从手写汇编到高级语言过渡时,"能读机器码"成了稀缺技能;现在"能判断 AI 代码是否正确"正在成为新的专业壁垒。这个壁垒不是语法层面的,是系统层面的——知道 AI 可能在什么地方偷懒、什么地方 hallucinate、什么地方用了过时的模式。
不可替代的核心能力
如果让我列几个 AI 短期内拿不走的 Android 开发能力,大概是这些:
第一,平台演进的前瞻判断。Android 15 的 predictive back gesture、16 可能强制的 edge-to-edge 适配、Health Connect 的标准化、Privacy Sandbox 的广告替代方案——这些不是代码问题,是产品和技术路线的决策。一个应用要不要现在投入适配 edge-to-edge,取决于目标用户的 Android 版本分布、竞品动向、Google 的强制执行时间表。这需要持续跟踪 Android 开发者博客、Google I/O 的 session、AOSP 的 commit 历史,甚至 Google 反垄断诉讼里暴露出来的内部邮件。AI 能总结已知信息,但做不出基于不完全信息的赌注。
第二,性能优化的深度诊断。Systrace 里一帧的绘制时间拆解、GPU 过度绘制的层级分析、内存分配的 GC 压力点、电量消耗的后台唤醒链——这些诊断需要理解 Android 系统的完整图景,从 SurfaceFlinger 的合成策略到 JobScheduler 的批量调度。AI 可以指出"这里可能有内存泄漏",但定位泄漏源、判断修复优先级、评估对用户体验的实际影响,需要经验。
第三,跨平台方案的取舍。一个产品用纯原生、Flutter、React Native、还是 Compose Multiplatform,这个决策涉及团队技能栈、发布节奏、平台特性需求、长期维护成本,没有标准答案。AI 可以罗列各方案的优缺点(而且往往罗列得很表面),但无法替一个具体团队做选择,因为它不理解这个团队的历史债务、人员流动率、业务压力。
第四,也是最实际的:线下问题的现场解决。用户手里千奇百怪的真机环境,日志采集不全、复现条件不明、网络环境不可控。远程诊断和逐步排查需要的不是代码生成,是系统性的假设检验和验证设计。AI 可以建议"尝试捕获更多日志",但设计一个最小侵入的远程诊断方案、在隐私合规的边界内获取足够信息、从模糊的用户描述中提取技术线索——这些能力目前完全在人类这边。
一个具体的判断
我的个人观点:未来三到五年,Android 开发的"入门门槛"会大幅下降,但"专业门槛"会上升。AI 让写出一个能跑的应用变容易了,但写出一个在真实 Android 生态里健康运行的应用,难度没有降低,甚至可能升高——因为 AI 生成的代码掩盖了复杂性,让开发者对底层机制更加无知,出问题时的诊断更加困难。
Google 在 2024 年的 Android 开发者峰会上强调"AI 辅助开发",但同期发布的 Android 15 开发者预览里,平台行为限制反而更多了。这个张力会持续:AI 让代码产出更快,平台让合规要求更严,中间的缝隙就是专业开发者的生存空间。
我不担心 AI 取代 Android 开发,我担心的是"AI 辅助"变成"AI 依赖"后,新一代开发者对平台机制的理解断层。就像现在很少有人需要理解虚拟内存分页,但内核开发者仍然稀缺且高薪;Android 开发可能会分化成"用 AI 搭应用的"和"能修 AI 搞砸的"两个层次,后者的价值反而凸显。
你现在打开 Android Studio,新建一个项目,AI 能帮你生成完整的 Navigation 组件 + ViewModel + Repository + Room 的脚手架。但当你需要在 Android 14 上支持部分照片访问权限(Photopicker 的新模型)、同时兼容国内厂商各自的照片选择器定制、还要处理用户每次只授权部分图片后的缓存策略更新——这个场景里没有现成的 AI 模板,GitHub 上的开源实现各说各话,官方文档的示例代码刚更新到 beta 版本。你怎么办?
这就是答案。