第一章 AI编程入门

做为一个程序员,用AI进行辅助编程是早晚的事,头铁嘴硬的人最终都会变成小丑。

从今天开始,笔者的博文将会使用ChatGPT进行辅助编写,以前一些理论性的概念为了确保正确性,前后得搜好几篇博客相互印证对比才敢确定,同时想做一个表格也得手打,现在都不是问题了。

模仿贾队长的话来说,AI来之前我干活慢、写不出牛逼的代码,AI来之后我干活还慢,那他妈AI不白来了吗?

按照老规矩,先了解一些AI相关的基础知识吧。

什么是 AI 大模型?

定义

AI 大模型(Large AI Model)是指参数规模巨大、能力全面的人工智能模型,它们通过深度学习训练,能够处理自然语言、代码、图像、音频等多种任务


核心特点:

  1. 超大参数量:通常拥有 数十亿到万亿级 参数,如 GPT-4o、Claude 3.7。
  2. 通用能力强:可用于对话、翻译、代码、创作、推理等任务。
  3. 多模态支持:部分大模型支持文本、图像、音频、视频输入(如 Gemini 1.5)。
  4. 训练基于海量数据:模型从互联网文本、代码库、学术论文等数据学习。
  5. 自监督学习:无需明确标注数据,通过预测下一个词或填空的方式进行训练。

广为人知的 AI 大模型(截止至2025年3月28日)

模型名称 开发公司 特点 强项 应用场景
GPT-4.5(Orion) OpenAI 大型多模态语言模型,支持15种语言 多语言理解与生成 自然语言处理、内容创作、翻译等
Grok 3 xAI 强大的聊天、编码与推理能力 数学、科学与代码生成 [编码强] 编程辅助、科学研究、教育等
DeepSeek-V3-0324 深度求索 开源模型,专注于数学、编码及中文处理 数学与编程能力 [编码强],性价比高 数学求解、代码生成、中文自然语言处理等
Gemini 2.5 Pro 谷歌 增强型AI模型,提升推理能力 理解、数学、编码 [编码强]及多模态处理 复杂问题解答、编程辅助、多媒体内容生成等
Ernie 4.5 百度 升级版AI模型,具备增强的推理与多模态处理能力 多数据类型处理与转换 内容生成、数据分析、多媒体处理等
Claude 3.7 Sonnet Anthropic 专注于安全性和可控性的AI模型 高可靠性与安全性 医疗咨询、法律分析、教育辅导等
Llama 3.3 7B Meta 开源模型,擅长数学、常识及指令遵循 性价比高 教育、研究、开发等领域
Qwen2.5-Omni-7B 阿里巴巴 多模态处理,支持在智能手机上运行 移动端兼容性及多模态处理 智能助手、多媒体生成、实时翻译等
讯飞星火认知大模型 科大讯飞 具备文本生成、语言理解、知识问答与逻辑推理等核心能力 多领域应用能力 教育、医疗、智能客服等
文心一言大模型 百度 能理解复杂提示词,支持多模态生成 文学创作与商业文案撰写 文学创作、商业文案撰写、多模态生成等


其实基于不同的划分方法,大模型还可以继续细化:

类型 描述 示例
通用大模型 处理多种任务和数据类型,适用于广泛应用场景 GPT-4, Claude, Gemini, DeepSeek, 文心一言
专业领域大模型 针对特定专业领域(如编程、医学、法律、金融等)进行优化 Code Llama, DeepSeek Coder, BioGPT, 专业法律大模型
多模态大模型 同时处理文本、图像、音频等多种数据,实现跨模态生成与理解 DALL·E, Stable Diffusion, Gemini 2.5 Pro, Qwen2.5-Omni-7B
开源大模型 开放源码,便于社区二次开发和定制,适合研究及多场景应用 Meta 的 Llama 系列(如 Llama 3)、Mistral
垂直领域知识大模型 针对特定行业或领域(如教育、科研、工业制造等)整合专业数据与知识,提供精准决策支持 金融大模型、医疗大模型、教育大模型

通过以上这些不同类型的大模型,开发者可以根据具体应用场景选择最合适的模型,既能利用通用模型的广泛适用性,也能发挥专业领域模型在特定任务上的优势。

ChatGPT 与 GPT-4.5 是什么关系?

维度 ChatGPT GPT-4.5
定义 一个面向用户的聊天对话平台,用于与用户进行自然语言交互 一个大型自然语言处理模型,提供文本生成和理解能力
核心功能 提供交互式对话、问答、内容生成和辅助编程等服务 作为引擎支持各种自然语言处理任务,如生成、翻译、推理等
用户视角 用户直接与 ChatGPT 交互,获得即时答案和建议 用户通常不直接与 GPT-4.5 交互,而是通过应用或 API 间接使用该模型
开发者视角 集成和构建基于 ChatGPT 的产品和服务 用作核心 AI 技术,通过 API 或集成到产品中提供强大语言理解与生成能力
更新方式 版本更新可能涉及整体产品功能的迭代 独立发布和更新,当前最新版本为 GPT-4.5(Orion)
作用比喻 汽车(展示和操作平台) 发动机(提供动力和核心技术)

拓展: GPT-4.5 与 GPT-4o 的关系

根据 OpenAI 官方页面的信息,GPT-4.5 是在 GPT-4 技术基础上进一步改进的版本,主要针对文本任务进行了性能优化、推理能力提升以及更高效的运算,而 GPT-4o 则是一个全新的多模态模型,支持文本、图像等多种输入方式。

这意味着:
GPT-4.5:侧重于文本处理和对话的改进,是对原有 GPT-4 的增量升级,提升了推理速度和准确性。
GPT-4o:扩展了多模态能力,能够处理文本和图像等多种数据输入,提供更加丰富的交互体验,同时也在速度和成本上做出了优化。

因此,GPT-4.5 和 GPT-4o 是基于 GPT-4 技术的不同产品,它们各自针对不同的应用场景进行优化和升级,并非同一模型的不同版本。

编码能力强的大模型

最上面第一个表格都是由 ChatGPT 生成的,我要求它针对编码能力强的模型重点标记,有点AI经验的读者可能发现,最常用的“Claude 3.7 Sonnet”并没有被打上编码强的标签,于是我继续让它对此做出解释:

模型名称 优势 劣势 应用场景
Claude 3.7 Sonnet 在通用编码任务和多模态处理上表现均衡;部分 SWE 编码测试中准确率较高 针对某些特定任务(如数学推理、中文深度处理)可能表现略逊 通用开发、跨语言与跨领域编码任务
DeepSeek-V3-0324 在数学推理、前端开发以及中文编程任务上具有明显优势;性价比高 在一些广泛的通用编码任务中可能不如 Claude 3.7 Sonnet 均衡 针对中文和特定领域需求的编程任务

结论:

目前的信息显示,Claude 3.7 Sonnet 和 DeepSeek-V3-0324 各有千秋,具体优劣取决于任务要求和测试标准。  
- Claude 3.7 Sonnet 更适合需要处理多模态数据和广泛通用编码任务的场景;  
- DeepSeek-V3-0324 则在数学推理、前端开发以及中文处理等特定任务中展现出更强的优势。
因此,两者的编码能力无法简单地用“谁强谁弱”来一概而论,最好根据具体应用场景选择适合的模型。

AI 编程助手

下面是当前热门 AI 编程助手及其特点(截止至2025年3月28日)

AI 编程助手 开发公司 主要特点 适用场景
GitHub Copilot GitHub / Microsoft 基于 GPT 系列,自动代码补全;深度集成 VS Code 等 IDE 代码补全、函数建议、Pair Programming
Amazon CodeWhisperer Amazon 针对 AWS 优化,支持多种编程语言;高效生成代码建议 云端开发、API 集成、自动代码生成
Cursor AI Cursor 类 ChatGPT 编程助手,支持 Figma 解析与 UI 代码转换;智能代码优化 前端/移动端代码生成、UI 转换、自动化编程
Tabnine Tabnine 本地运行,隐私友好;支持个性化训练和多语言补全 多语言代码补全、隐私敏感项目
Codeium Exafunction 免费且轻量,支持70+编程语言;响应速度快 快速代码补全、跨语言开发
DeepSeek Coder DeepSeek 开源模型,专注代码生成与中文优化;数学与编程能力突出 中文开发、代码生成、AI 编程研究
Code Llama Meta 开源 AI 编程助手,支持本地部署;适合离线和嵌入式开发 开源开发、离线代码生成、研究与实验
PolyCoder OpenAI 专注于代码生成,多语言支持;针对编程任务进行专门优化 自动代码生成、编程研究、特定语言模型试验
Trae AI 字节跳动 AI 原生 IDE,提供 Chat 模式与 Builder 模式;支持端到端项目生成和 UI 解析 自动项目搭建、端到端代码生成、跨平台 UI 转换

仅仅是助手

最初在抖音看到有人介绍 Cursor 的用法,发现都是针对网页、小程序开发的简单介绍,顿时就没了兴趣,感觉对App开发没什么用。后来体验了几天 Cursor 之后,发现确实对编码有提效,但这个提效不是全方位的,而是在特定场景下的提效

首先,在使用 Cursor 进行辅助编程时,我会开启两个IDE,一个是 Cursor ,一个是 Android Studio 。

1、项目的编译、打包必须在Android Studio中进行, Cursor 完成不了。

2、虽然直接在 Cursor 里写代码,多一个代码提示功能(而这对我没什么用),但它的 IDE 的风格与快捷键与本人习惯完全不一致,我不想再去习惯它,所以常规的编码工作依然在Android Studio中进行。

3、只有当遇到需要辅助编程的场景,比如需要写一个自定义控件的时候,我会在 Cursor 中具体描述需求,由它来编写代码。同时为了不给自己找麻烦,在让 Cursor 写代码之前,我会把本地代码提交一下,如果它写的不满意,就他妈直接回滚。

其次,AI 写出的代码质量和你描述需求的能力成正比。

如果你只传递一个png格式的设计稿,并告诉他帮我写一个大转盘的功能,那得到的结果大概率是你不满意的。
第一个问题就是,它可能会把大转盘的类文件放到一个你不满意的包下面。
第二个问题,它可能会用xml的方式聚合多个view,来实现你的需求,比如一个ImageView展示转盘,一个ImageView展示指针。
第三个问题,转盘的转动效果你不满意,它可能就给你转个3圈,而且开始和结束的速度是一样的。

稍微好一些的提需求方式是:
你帮我在home/dialog包下创建一个抽奖对话框,对话框的样子是我传递给你的png图所展示的样子。
转盘的图片你可以用bg_lottery.png,指针的图片用ic_lottery_arrow.png。
同时要求通过自绘View的形式来实现转盘功能,转盘包含4个奖品,它们按照顺时针方向排列,中奖概率依次为10%、20%、30%、40%。

即便你像上面描述的这么细致,依然不可能一口气就把功能实现,通常你需要经历多轮的沟通后,才会有一个比较满意的结果,虽然如此也一定会比自己从头写要快。

第三,不要神话它目前阶段的能力,以我目前的使用体感来说:

1、不要把编程助手想象成“诸葛亮”,没有那么强。如果你打算在你的老项目中直接使用 AI 编程助手,不论你需求描述的多么详细,AI编程助手都很难在一次沟通中就实现你的完整需求(若此时你想抬杠请走开)。因为 AI 编程助手并不会整体扫描你的整个项目,深入理解你的每行代码的逻辑,它只是在接到你的命令时,小范围的理解代码,并依据需求来生成代码,所以不可避免的出现意料之外的结果。

2、你应该调整自己的角色定位,从“一线编码人员”转变成“架构师”、“小组长”的角色。即由你来事先统筹项目架构、拆分需求,然后再由AI来帮你实现功能。

3、目前看起来,越是独立的功能模块(比如自定义控件、给图片加水印等工具方法),AI的提效能力越大。

第四,助手懂得多。

AI编程助手可以编写所有类型的项目,游戏、APP(Android、iOS)、网站、小程序等等。
所以不论你是哪个工种,都可以使用AI编程助手,本文档是以Android为切入点,但这东西都是一通百通。

到底选谁?

这取决于你对 AI 编程助手的需求:

假设 Cursor 提供了1万个功能,但你都用不到,你的需求只是写个简单爬虫、创建 html5 的小工具,而这些功能任何一个 AI 编程助手都可以实现,你干嘛要选收钱的呢?
另外,AI 编程助手本身是一直在变化的,大家应该做的不是几选一,而是都去了解、使用,用发展的眼光去看待 AI 编程助手,不要只盯着眼前。

我最开始使用的是 Cursor ,但免费用户是有限额的,在我发出了一个让 Cursor 将大量 Java 类转到 Kotlin 类的命令时,限额用完了,我第一反应就是去使用 Trae AI 了,既然大家使用的大模型都差不多,为什么要交钱?

万万没想到,大聪明不止我一个,此时此刻至少还有 506 个:



既然免费的需要排队,那肯定不能用在实际生产中了,目前看起来只能选 Cursor 了。
其实不全对,排队是因为 Claude-3.7-Sonnet 这个大模型比较火,换一个模型就好了,比如换成 DeepSeek-V3-0324。

需要注意的是,模型与模型之间的差异还是比较大的:

比如我先用 Claude-3.5-Sonnet ,让它帮我生成一个界面,界面中间放一个按钮,点击后展示“Hello World”。
虽然它创建的 Activity 是对的,但将 Activity 写入到清单文件的时候,写到<manifest>外面去了。
而换成 Claude-3.7-Sonnet 则没有这个问题。


目前看起来,Trae AI 似乎是一个不错的选择,可以用 DeepSeek-V3-0324 生成代码,本身还是免费的。
不过它并不一定合符你的需求,因为我接下来问了 DeepSeek 这么一个问题:

截止至2025年3月28号,Cursor 具备哪些 Android 开发功能,而 Trae AI 不具备?
功能类别 Cursor Trae AI
全栈开发支持 ✅ 深度集成VS Code生态,兼容Android Studio插件
✅ 支持复杂多模块项目构建
❌ 官方未提及Android原生开发支持
⭕ 专注Web/游戏快速原型开发
代码生成效率 ⏱️ 实测响应时间快3倍
📄 符合企业级规范(时间戳/API安全等)
⏳ 复杂逻辑理解不足
⚠️ 可能出现依赖配置错误
Android语言支持 🔧 原生支持Java/Kotlin
🚀 自动生成Jetpack Compose布局代码
🔴 未明确支持Kotlin/Jetpack
🟡 主要支持Python/JavaScript
调试能力 🔍 精准定位Android特有错误(如CursorWindowAllocationException
📌 提供修复建议
🛠️ 侧重Web应用调试
🚫 无ANR/内存泄漏针对性支持
跨平台兼容性 🌐 Windows/macOS/Linux全支持
⚙️ 集成ADB/Gradle工具链
🍎 仅支持Mac系统
🔗 未整合Android开发环境
典型场景示例 📱 生成多线程安全的数据库操作代码
🔗 自动处理Activity/Fragment生命周期绑定
🕹️ 快速生成2D小游戏逻辑
🌍 创建简单CRUD网页应用

总结:

Cursor 在 Android 开发中拥有直接解析 Figma 设计、生成 Jetpack Compose 和 XML 布局代码的优势,同时还具备 API 绑定、Gradle 优化以及代码语言转换等高级功能。
Trae AI 则主要侧重于整体项目搭建和快速原型开发,缺乏针对 Android 平台的深度代码生成和优化功能。

如果你是 Android 开发者,Cursor 绝对是更好的 AI 助手!
如果你是 iOS 开发者,答案也是一样的,不信的话就自己去问ChatGPT。在以前,脑袋里有千百个问题但周围没人有能力回答你,慢慢的就不会问了,现在不同了,只要你有问题,那就一定能得到答案,答案可能不对,但你就说有没有吧?



最后再问一个问题:将一个 Android 项目,转换成 iOS 项目,用 Cursor 能实现吗?

如果你希望从 Android(Kotlin / Jetpack Compose / XML)转换为 iOS(Swift / SwiftUI / UIKit),Cursor 可以在以下几个方面提供帮助:

转换内容 Cursor 支持?
UI 布局(Jetpack Compose ➝ SwiftUI) 可以部分转换,需手动调整
UI 布局(XML ➝ UIKit / Storyboard) 可以部分转换,但可能需要调整 Autolayout
业务逻辑(Kotlin ➝ Swift) 可以辅助代码转换,但无法完全自动化
网络请求(Retrofit ➝ Alamofire / URLSession) 可以自动转换 Retrofit 调用至 Swift 网络库
数据库(Room ➝ CoreData / Realm) 可以转换基本的数据存储逻辑
Android API(Jetpack API ➝ iOS API) 部分 API 需要手动适配
第三方库(Android-only 库 ➝ iOS 版本) 需要手动查找替代方案
Gradle 配置 ➝ Xcode 项目设置 需要手动配置 Xcode

结论:

1、Cursor 可以帮助自动转换 UI & 业务逻辑,但 iOS 适配仍需要手动调整,无法做到 100% 自动转换
2、适合小型项目或单个组件的迁移,不适用于完整复杂项目的全自动转换


这么说的话,那换一个问题:是将 Android 转换成 iOS 成本大,还是转成 Flutter 或者 React Native 成本大?

如果你的目标是让 Android 应用运行在 iOS,主要有两种方案:
1️⃣ 直接转换为 iOS(Kotlin ➝ Swift / Jetpack Compose ➝ SwiftUI)
2️⃣ 转换为跨平台框架(Flutter / React Native),实现一套代码适配两端

那么,哪种方案的成本更低?让我们从 代码迁移难度、维护成本、长期扩展性 等方面对比👇

对比项 Android ➝ iOS(Kotlin ➝ Swift) Android ➝ Flutter / React Native
代码复用率 (大部分代码需手动迁移) (大部分业务逻辑可复用)
UI 适配 Jetpack Compose ➝ SwiftUI / UIKit 需要大量重写 Flutter / React Native 可共用 UI
开发成本 💸 (需要 iOS 专业开发) 💸💸 中等(Flutter > React Native)
维护成本 (Android & iOS 维护两套代码) (一套代码,两端运行)
性能 原生性能最佳 🔄 Flutter 接近原生,React Native 略逊
API 兼容性 Android API 需全部重写成 iOS API Flutter / RN 直接封装平台 API
适用场景 已有 iOS 代码或长期专注 iOS 生态 想减少维护成本 & 适配多平台

结论:哪个方案更划算?

你的情况 推荐方案
已有大量 iOS 代码,或已有 iOS 团队 直接转换为 iOS(Kotlin ➝ Swift),成本最高,需要维护两套代码,适合已有 iOS 代码库或团队
希望尽量少改动代码,快速上线 iOS 版 Flutter / React Native,一套代码适配 Android & iOS,长期维护更轻松
未来还要支持 Web / 桌面端 Flutter 更适合
对性能要求极高(如游戏、AR、AI 应用) 原生 iOS 更优

Cursor

关于 Cursor 如何安装,我就不赘述了。就像之前说的,我会同时使用 Cursor 和 Android Studio 。所以在 Cursor 中我没有去修改主题色、字体大小、安装什么 Kotlin 插件等的,唯一只干了一件事,安装中文插件。



一切就绪之后,会看到如下内容,你可以选择打开本地项目,或者直接拉取远程项目。



2048游戏

下面笔者将以一个“2048”的项目为示例,来介绍 Cursor 的最初级用法。
首先按照上面的示意,选择“Open project”按钮,找到一个你想要的位置,创建一个名为“2048”的文件夹,接下来 Cursor 生成的代码会放到该文件夹下面。

直接 Cursor 右上角的对话框里输入:帮我生成一个网页版的2048游戏。



接到命令后,Cursor 就开始生成代码了,很显然为了代码的维护性,它不会将所有的代码都写在一个文件里,所以生成代码的时候也是依次生成,上图中可以看出,优先生成的是 index.html 文件。

每个文件生成完毕后,不会立即保存,由你来阅读确认之后,点击文件框右上角的“✔️”按钮后,才会保存文件。

由于生成代码的速度很快,所以大部分情况下是,你还没看完第一个文件的代码,第二就生成完了,所以你可以点击上图我红框框起来的按钮,一键保存所有文件(由于我截屏的时候AI只写完了一个,所以按钮的文案是“Accept”,如果是写完了多个则文案就是“Accept All”)。

最终的效果也很不错,如下图所示:



三种模式

与 Cursor 沟通时,可以选择 Agent Ask Edit 三个模式。



模式 是否可修改代码 适合的任务 不适用场景
Agent 可以 复杂代码生成、跨文件修改、自动化重构、完整项目管理 可能改动过大,不适合小范围微调
Ask ⚠ 间接可以 三种模式中,最全面的代码解释、优化建议、提供修改思路 不会直接修改代码,需要手动操作
Edit 可以 单文件代码优化,局部重构、bug 修复 不能跨文件修改,适用于小范围调整,涉及多个文件 Edit 可能无法正确处理全部依赖关系

需要注意的是,在 Cursor 最新版本中, Edit 模式改名为 Manual 了。

We've also renamed "Edit" to "Manual" to better reflect its behavior.

解决实际问题

虽然上面写出的 2048 游戏确实很厉害,但这对提升我工作效率没什么屌用。
事实上信任是需要逐步建立的,招来个新人也是从一开始的小需求开始,做的好就继续上强度,与 AI 编程助手的相处也是类似。

一开始接触 AI 编程助手时,可能一时半会反应不过来该指挥它去做什么,主要是不知道它的上限在哪,生怕提个复杂点的需求它搞不定,还把代码搞乱了。因此我在决定用 AI 助手写代码之前,会先把本地代码提交干净。

就像当 ChatGPT 刚出来的时候,也不知道问什么问题能有效的帮助自己,随着慢慢对它的熟悉之后,就能高效使用了,比如:

我看到一个海外华人博主电动汽车自燃,保险公司拒赔,它就问了 ChatGPT 拒赔是否合法,结果 ChatGPT 找到了合同漏洞,并按照博主的要求“以白人的口吻写出一封索赔邮件,要有理有据,暗含威胁”,最终保险公司配了他几万刀。

那么好的,正好手上有个小问题需要写脚本处理一下。
我手上有3个json文件,里面保存了3组图片,我需要将前100张图片对应的zip下载到本地,最后内置到APK里,由于这3个json的内容很容易变动,且相互之间有重复的图片,要是每次手动下载zip就很恶心与浪费流量,所以就提出了如下需求:

写个脚本,从当前文件夹中读取base_1、base_2、daily三个文件,同时需要对内容进行base64解密,得到真实的json数据。 
然后将base_1、base_2两个文件的imageList字段下前100条记录,以及daily文件的前10条记录融合在一起。 融合的时候需要排重,以元素的id字段为排重依据。 
接着遍历融合后的元素列表,若某个元素的resource字段对应的文件,在/Users/cutler/xx/image目录下存在则将文件复制到当前目录的images目录下,若不存在则触发文件下载,并保存到当前目录的images目录下。
最后输出融合后元素的总个数,以及本次下载文件的个数。

经过几轮的沟通(有我需求的变化,也有它写的代码有问题),最终得到如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import json
import base64
import os
import shutil
import urllib.request
from urllib.error import URLError

def read_and_decode(filepath):
with open(filepath, 'r') as f:
encoded_data = f.read()
decoded_data = base64.b64decode(encoded_data).decode('utf-8')
return json.loads(decoded_data)

def main():
# 读取并解码三个文件
base1 = read_and_decode('/Users/cutler/workspace/ai/level/base_1')
base2 = read_and_decode('/Users/cutler/workspace/ai/level/base_2')
daily = read_and_decode('/Users/cutler/workspace/ai/level/daily')

# 收集所有元素,以id为键去重
merged = {}

# 处理base_1的前120条记录
for item in base1.get('imageList', [])[:120]:
if 'id' in item:
merged[item['id']] = item

# 处理base_2的前120条记录
for item in base2.get('imageList', [])[:120]:
if 'id' in item:
merged[item['id']] = item

# 处理daily的前20条记录
for item in daily.get('imageList', [])[:20]:
if 'id' in item:
merged[item['id']] = item

# 创建images目录
os.makedirs('images', exist_ok=True)

# 统计下载文件数
download_count = 0

# 遍历融合后的元素
for item in merged.values():
if 'resource' in item:
resource = item['resource']
filename = resource.split('/')[-1]
src_path = f"/Users/cutler/workspace/android/level/app/src/main/assets/image/{filename}"
dst_path = f"images/{filename}"

if os.path.exists(src_path):
shutil.copy2(src_path, dst_path)
else:
print(f"准备下载: {resource}")
try:
# 临时禁用SSL验证
import ssl
import time
ssl._create_default_https_context = ssl._create_unverified_context

# 添加重试机制
max_retries = 3
retry_delay = 2 # 秒

for attempt in range(max_retries):
try:
urllib.request.urlretrieve(resource, dst_path)
download_count += 1
print(f"成功下载: {filename}")
break
except (URLError, ConnectionResetError) as e:
if attempt == max_retries - 1:
print(f"下载失败: {resource} - 错误: {str(e)} (尝试 {max_retries} 次后)")
else:
print(f"下载失败,第 {attempt + 1} 次重试...")
time.sleep(retry_delay)
except Exception as e:
print(f"下载失败: {resource} - 错误: {str(e)}")

# 输出统计信息
print(f"本次共下载了 {download_count} 个文件")
print(f"融合后共有 {len(merged)} 个元素")

if __name__ == '__main__':
main()

如果沟通过程中出现了错误,直接将错误信息复制给 Cursor 就行,多一个字不用说,它就可以自己寻找原因并解决,大概率能解决掉。

这对于编程初学者来说,并不是一个多好的消息,直接放弃思考了,且上瘾性比较强,对个人排查问题的能力有很大的弱化。


有了这个 Python 代码后,当这三个文件内容有变化时,直接执行它就可以了,如果你的电脑上没有安装 Python ,那么 Cursor 和 Trae 都会询问你是否安装,若同意则自动帮你下载安装。

其实几年前我学过 Python 但工作中从来没用过,以至于学的东西几乎全忘了,唯一记得的是 Python 没有大括号直接通过缩进来表示层级。
但是有了 Cursor 那就太方便了,写我虽然写不出来,但通过看它写的代码,来排查逻辑那指定是一点问题没有。

解决实际 Android 问题的过程还原

目前为止,我用 AI 编程工具 完成了3个需求:

第一个是上面提到的大转盘相关的2个自定义控件
第二个是上面的脚本
第三个是 Android 里的 RecyclerView 手势算法

本节主要介绍第三个需求的实现过程,下面是代码的现状以及新的需求:


首先我的项目中有一个名为“ MyRecyclerView ”的类,用来展示一个水平方向的列表。
当用户按下并拖动某个 Item 时,我会计算用户手指在 水平 垂直 方向上已经拖动的距离,若满足一定的阈值(比如水平在 10 像素以内,垂直在 10 像素以上),我就认为用户此时正在向上拖动这个 Item ,则就会拦截 MyRecyclerView 的事件,不让它继续支持水平滚动,然后执行后续逻辑。

现在需求有变,要求按照“ 用户手指拖动的角度 ”来判断用户的意图,若用户手指拖动的角度在 45 度以内(包含左上方、正上方、右上方三个方向),则认为用户正在向上拖动这个 Item ,则就会拦截 MyRecyclerView 的事件,不让它继续支持水平滚动,然后执行后续逻辑。


那么好的,接下来是我与 Cursor 的对话过程。

首先我试探性的问了一句:

MyRecyclerView类的isTouchingItem变量你知道干什么用的吗?

主要是看看他到底能不能理解代码的上下文,如果连理解都做不到,那还是拜拜吧。

Cursor 接到问题的第一个反应是:“让我搜索一下MyRecyclerView类”
……
搜搜完毕后,确实给出了差不多正确的反馈,不过此时也让我意识到,我提的需求并不完整,以至于它还需要先去找这个类在哪。

然后我开始正式提出需求:

我想将isTouchingItem置位true的条件改一下,若用户按下的点与首次move的点之间,距离y轴原点夹角小于45度,则走后续逻辑。 需要注意的是需要处理两个方向的逻辑,就是左上,右上,都需要判断45度角。

一通操作之后,代码确实写出来的,但是报错了,我直接将错误信息交给它,让它修改:

1
2
e: file:///Users/cutler/workspace/android/aaaa/app/src/main/java
/com/aaa/aaa/aaa/aaa/widget/MyRecyclerView.kt:25:20 Unresolved reference: toDegrees

这是因为他引用的kotlin.math.toRadians函数我本地没有,后来它换成了Java的Math.toDegrees函数就可以了。
大致的代码是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
// 计算移动点与按下点之间的角度
val deltaX = event.x - downX
val deltaY = event.y - downY
val angle = Math.toDegrees(atan2(deltaY.toDouble(), deltaX.toDouble()))

// 判断是否在45度角范围内(只处理左上方和右上方)
val isWithinAngle = when {
// 第一象限(右上):0-45度
deltaX >= 0 && deltaY <= 0 && angle in 0.0..45.0 -> true
// 第二象限(左上):135-180度
deltaX <= 0 && deltaY <= 0 && angle in 135.0..180.0 -> true
else -> false
}

这代码不用跑就知道有问题,但为了证据确凿,我运行并打印了变量angle的值,并告知 Cursor 现在的情况:

你的角度是不是算错了,我往右上方滑动手指,打印出的angle都是负数

它此时也反应过来的,回复到:

啊,我明白问题所在了。在Android的坐标系中,Y轴是向下为正,而我们在计算角度时需要考虑这个坐标系的特点,让我修改一下代码。

运行之后,依然不对,于是我们进行如下对话:

还是不对。我现在从下往上垂直滑动,打印出的角度是90,按我的预期应该是0。
啊,我明白了。我们需要调整角度的计算方式,让垂直向上的方向为0度,让我修改一下代码。
……
左上角的判断似乎是错的。也应该相对于垂直方向往左45的,我觉得应该是315到360度才对
您说得对,我理解错了左上方的角度范围。让我修改一下代码
……
那右上方的判断条件是否需要变化一下?
是的,您说得对。既然左上方是315-360度,那么右上方应该是0-45度。让我修改一下代码

至此得到最终的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
// 计算移动点与按下点之间的角度
val deltaX = event.x - downX
val deltaY = event.y - downY
// 计算与垂直向上方向的夹角(0度为正上方)
val angle = (Math.toDegrees(atan2(deltaX.toDouble(), -deltaY.toDouble())) + 360) % 360
// 判断是否在45度角范围内(只处理左上方和右上方)
val isWithinAngle = when {
// 右上方:0-45度
deltaX >= 0 && deltaY <= 0 && angle in 0.0..45.0 -> true
// 左上方:315-360度
deltaX <= 0 && deltaY <= 0 && angle in 315.0..360.0 -> true
else -> false
}

在上面的聊天过程中,虽然 Cursor 看起来像是一个新兵蛋子,但他解决我最重要的问题“计算角度”,对于我这种大专巅峰的学者来说,一般都懒得去学三角函数这种低级的招数。

Trae AI

Trae AI 的安装过程更简单了,而且还是免费的,如果你的 Curosr 达到限额,且不需要使用 Cursor 的高级功能,那么用它写 Android 也是没问题的。

唯一需要知道的就是,Trae AI 分为 “Chat” “Builder” 两个模式。



这两个模式的对比如下:

模式 Chat 模式 🗨️ Builder 模式 🏗️
核心功能 类似 ChatGPT,提供代码问答、调试、解释 AI 直接生成完整项目,自动化编程
适用场景 代码查询、修复、优化、理解代码逻辑 生成完整项目、组件、API,甚至端到端的应用
交互方式 开发者与 AI 进行对话式交互,逐步修改代码 AI 根据需求生成项目,开发者可调整和优化
代码补全 ✅ 支持 ✅ 支持
代码解释 ✅ 提供代码段解析 ❌ 主要是代码生成
自动编程 ❌ 以问答为主,需要手动实现 ✅ AI 负责编写核心代码
适合用户 需要即时代码帮助、调试、优化的开发者 想用 AI 快速搭建项目、组件的开发者

🤔 那如果把 Builder 模式当 Chat 模式用,会有什么问题?

问题类型 可能的影响
输出方式不同 Builder 模式更倾向于生成完整项目,而不是逐步回答问题。你可能只是想问一个小问题,但 Builder 可能直接给你一堆代码。
缺少交互性 Chat 模式可以像 ChatGPT 一样逐步引导你优化代码,而 Builder 更像是“一次性”生成代码,交互性较弱。
代码解释能力弱 Chat 模式擅长解释代码、分析错误,而 Builder 主要负责代码生成,不会详细解释它为什么这样写。
计算资源消耗更大 Builder 可能会调用更多计算资源来生成完整代码,而 Chat 只处理小片段,使用 Builder 可能会导致不必要的性能开销
适用场景不匹配 Chat 模式适合问答、修复,Builder 适合自动创建项目。如果你只是想问一个小问题,Builder 可能会“过度执行”。

🚀 也就是说:
如果只是想问问题、改代码、优化逻辑,请用 Chat 模式
如果你想让 AI 生成一个完整项目或功能,用 Builder 模式 更合适!
如果你打算开启一个全新的项目,那么你可能会先用 Builder 生成,然后用 Chat 小步迭代。