AI辅助开发:为智能手表打造番茄钟与待办应用

发布时间:2026/10/19 2:22:22
AI辅助开发:为智能手表打造番茄钟与待办应用
1. 为什么我要给一块旧手表写个番茄钟手上这块华米Amazfit GTR4大概是两年前入的当时图它续航长、屏幕常亮、能装第三方小程序官方叫法是手表应用用了一阵子之后新鲜劲过了就沦为看时间和收通知的工具表。直到最近我重新捡起番茄工作法想找个能在手腕上直接计时、还能顺手记待办的小工具翻遍了应用市场都没找到特别顺手的——要么功能太重、要么界面丑、要么同步逻辑反人类。于是我就动了念头既然这表支持装自定义应用那我干脆自己写一个。问题是我已经很久没碰过嵌入式前端那套东西了手表端的小程序开发框架跟常规Web开发差别不小文档又散。这时候我想到了用AI coding来辅助——不是让它替我全写完而是把它当成一个随时在线的结对搭档帮我快速过掉那些查文档、试API、调布局的脏活。这篇文章就是整个过程的完整复盘。我会讲清楚这块表上的应用到底是怎么跑起来的、番茄钟和待办这两个功能在手表这种小屏低功耗设备上要怎么设计、AI coding在哪些环节真正帮上了忙、哪些坑它反而会带你掉进去。如果你手上也有一块吃灰的智能手表或者你正在琢磨怎么把AI coding用到实际的小项目里这篇应该能给你省下不少时间。先说结论整个项目从零到能日常用大概花了三个周末的碎片时间核心代码不到一千行其中AI帮我生成的初稿占了大概六成但真正让它能用的是我后面反复手改的那四成。这个比例很关键后面会展开讲。2. 先搞清楚这块表到底能跑什么2.1 手表应用的运行环境与限制在动手之前必须先弄明白Amazfit GTR4这类设备上的应用到底是什么形态。它跟手机上的App完全不是一回事本质上是运行在手表RTOS之上的轻量级小程序官方提供了一套基于JavaScript的开发框架界面用类似声明式的语法描述逻辑层跑在受限的JS引擎里。这意味着几件事你得提前接受第一没有完整的DOM你不能像写网页那样随意操作节点界面更新靠的是数据绑定和状态驱动第二可用内存非常小官方文档里给的堆内存上限通常只有几百KB到一两MB这个量级你稍微多存几个大对象就可能崩第三没有本地数据库那种东西持久化存储只有键值对形式的小容量接口存个待办列表的JSON字符串还行想存大量历史记录就别想了。我一开始就是没吃透这些限制让AI按常规Web思路生成了一版代码结果在模拟器里跑得好好的一装到真机就白屏。后来才反应过来是初始化时一次性创建了太多视图对象直接把内存撑爆了。提示任何在手表上跑的应用第一原则是能少创建对象就少创建。界面元素尽量复用列表滚动时不要动态增删节点而是改数据让框架自己去diff。2.2 番茄钟和待办为什么适合放在手表上有人可能会问番茄钟和待办这种功能手机上不是一抓一大把吗为什么非要折腾到手表上我的实际体验是手表在这两个场景里有天然优势。番茄钟的核心是专注期间不碰手机。如果你用手机计时那手机就在手边通知一来你就分心了番茄工作法直接破功。而手表抬腕就能看剩余时间计时结束震动提醒整个过程你根本不需要解锁手机。待办也是同理想到一件事随手在手腕上记一笔比掏手机打开App再输入快得多记录的门槛越低你越愿意用。所以这个应用的设计目标很明确极简、抬腕即用、单手可操作。所有花哨的功能都是负担。我给自己定的功能清单就三条——开始/暂停番茄计时、到点震动提醒、快速增删待办项。就这三条做扎实就够了。2.3 技术选型的取舍框架层面其实没太多选择官方给什么就用什么。真正需要做决策的是状态管理和数据存储方式。状态管理我最终用的是最朴素的单一状态对象加手动触发更新。原因很简单手表应用的界面状态本来就少引入任何状态管理库都是杀鸡用牛刀还会增加包体积和内存占用。整个应用就维护一个state对象里面放着当前计时状态、剩余秒数、待办数组这几样东西任何改动都走同一个更新函数。数据存储用的是官方提供的键值对接口待办列表序列化成JSON字符串存进去启动时读出来反序列化。这里有个细节写入不要太频繁。我一开始每勾选一个待办就写一次存储结果发现手表在频繁写存储时会有明显的卡顿和耗电。后来改成延迟合并写入攒够一定时间或者退出应用时再统一落盘体验立刻顺滑了。决策点方案A方案B我的选择与理由状态管理引入状态库单一状态对象选B状态少库是负担数据存储每次改动即写延迟合并写入选B减少IO卡顿和耗电界面更新手动操作节点数据绑定驱动选B框架原生支持更稳计时实现每秒setInterval记录时间戳算差值选B避免后台被挂起导致计时不准最后一行那个计时实现方式特别值得说。手表应用在息屏或后台时定时器是可能被系统挂起的如果你用每秒减一的计数器一旦被挂起回来之后时间就全乱了。正确做法是记录一个开始时间戳每次刷新时用当前时间减去开始时间算出已经过了多久这样无论中间被挂起多少次算出来的剩余时间都是准的。这个坑我是踩过才知道的AI第一版给的就是每秒减一的写法真机上息屏再亮屏直接对不上。3. 番茄钟的核心逻辑怎么落地3.1 计时状态机的设计番茄钟看起来简单其实状态不少空闲、专注中、暂停、专注结束待确认、休息中。这几个状态之间的转换如果不用状态机来管代码很快就会变成一堆if-else的泥潭。我给AI的提示词里明确要求用状态机模式它给出的结构还算清晰定义了一个状态枚举和一张转换表。但AI犯了个典型错误——它把暂停和空闲当成了一回事导致暂停后无法恢复到原来的剩余时间。这就是AI coding的典型问题它能写出结构漂亮的代码但对业务语义的理解是表面的你得自己盯着。我手动修正后的状态转换是这样的空闲 → 专注中点击开始专注中 → 暂停点击暂停记录当前剩余秒数暂停 → 专注中点击继续从记录的剩余秒数接着走专注中 → 专注结束剩余时间归零触发震动专注结束 → 休息中自动或手动进入休息休息中 → 空闲休息结束关键在于暂停必须保存剩余时间这个中间态而不是简单地回到空闲。这个细节决定了用户体验是能接着走还是得重来。3.2 剩余时间的精确计算前面提到了计时不能用累减要用时间戳差值。具体实现是这样的进入专注状态时记录startTimestamp和totalDuration暂停时记录pausedRemaining。刷新界面时如果处于专注中剩余时间等于totalDuration - (now - startTimestamp)如果处于暂停剩余时间就是pausedRemaining。这里还有个精度问题。手表上刷新界面的频率不可能做到每秒精确一次可能因为系统调度有几十毫秒的抖动。如果你显示的是分:秒那这点抖动无所谓但如果你要做那种圆环进度动画就得用剩余时间占总时长的比例来算角度这样即使刷新不均匀视觉上也是平滑的。我实测下来用时间戳差值法即使手表息屏十分钟再亮屏剩余时间依然准确误差在可接受范围内。而累减法在同样场景下能差出好几分钟。3.3 震动提醒的触发时机震动是手表相比手机最大的优势之一但触发时机有讲究。番茄钟结束时我设置的是连续震动三次每次间隔半秒这样既不会太突兀又能确保你注意到。但这里有个坑如果应用在后台被系统冻结了你的定时器可能不会准时触发震动。解决办法是同时依赖系统的通知能力——在开始专注时就向系统注册一个在结束时刻触发的本地通知这样即使应用被冻结系统也会在到点时唤醒并震动。应用自己的定时器只负责界面刷新真正的提醒交给系统通知兜底。这个双保险机制是我踩坑之后加的。有一次我在专注期间切到别的应用结果番茄钟到点了手表一点反应都没有回来一看应用被挂起了。加了系统通知之后这个问题就再没出现过。注意注册系统通知时要注意权限和数量限制。手表上通知资源有限不要注册一堆用不上的通知用完记得取消。3.4 界面布局在小屏上的取舍GTR4的屏幕是圆形的分辨率不算高这就意味着你的布局必须围绕圆形来设计。方形的布局思路直接搬过来四个角的内容会被裁掉。我的主界面就三块内容中间一个大大的剩余时间数字下面一个圆环进度条底部两个按钮开始/暂停、重置。待办列表是另一个页面用上下滑动切换。整个界面没有多余装饰因为在小圆屏上任何多余的元素都会让信息变得拥挤。字体大小也调了好几轮。AI第一版给的字体偏小在模拟器上看还行真机上根本看不清。后来我把主时间数字调到了屏幕宽度的三分之一左右才达到抬腕一眼能看清的效果。这个只能靠真机反复试模拟器的显示比例和真机观感差别很大。4. 待办功能的数据结构与管理4.1 待办项的数据模型待办项的数据模型我设计得很克制就四个字段唯一ID、文本内容、是否完成、创建时间戳。没有优先级、没有标签、没有截止日期——不是不能加而是在手表这种输入条件下加这些字段只会让操作变复杂违背了随手记的初衷。ID的生成我用的是时间戳加随机数简单够用。这里AI又给了个聪明的方案说可以用UUID库我直接否了——为了生成个ID引入一个库在手表上纯属浪费。时间戳加随机数几行代码搞定冲突概率低到可以忽略。4.2 增删改查的交互设计手表上输入文字是个大问题。GTR4没有实体键盘虚拟键盘在小圆屏上打字体验很差。所以我的策略是新增待办时尽量让用户少打字。具体做法是提供一个快速添加入口点开后是一个预设的常用待办模板列表比如喝水站起来活动回复消息点一下就加进去了。如果确实要输入自定义内容再走虚拟键盘。这样日常使用中大部分待办都是两下点击搞定几乎不用打字。删除和完成的操作也很直接列表项左滑标记完成长按弹出删除确认。这两个手势在手表上都是系统级的通用交互用户不用学就会。4.3 存储的读写策略前面提过存储要延迟合并写入。具体实现是维护一个dirty标志任何对待办列表的修改都把dirty置为真然后启动一个短延时比如两秒的定时器延时到了且dirty为真才真正写存储并清除标志。如果在这两秒内又有修改定时器重置。这样即使用户连续勾选五个待办也只会在最后一次操作后写一次存储。实测下来这个策略让应用在批量操作时的卡顿感基本消失了。读取则是在应用启动时一次性读出来反序列化后放进内存状态里之后所有操作都基于内存不再读存储。手表应用的生命周期通常很短用户用完就退所以内存里的数据不会存在太久不用担心一致性问题。操作是否立即写存储说明新增待办否标记dirty延迟写入勾选完成否标记dirty延迟写入删除待办否标记dirty延迟写入应用退出是强制落盘确保不丢数据应用启动读取一次性读入内存最后一行应用退出强制落盘很重要。延迟写入虽然好但如果用户改完立刻退出应用而延迟定时器还没触发数据就丢了。所以必须在应用的生命周期回调里加一个强制写入这个AI一开始也没考虑到是我自己补上的。5. AI coding在哪些环节真正帮上了忙5.1 快速过掉框架的样板代码说实话这个项目里AI最大的价值不是写核心逻辑而是帮我快速搭起了框架的骨架。手表应用的入口文件、页面注册、生命周期钩子、基础的界面描述语法这些样板代码我虽然能查文档写出来但查文档本身就要花时间。我把官方文档的要点喂给AI让它生成一版骨架然后我在上面改效率比从零写高很多。比如界面描述那部分语法跟常规的HTML差别不小我让AI根据我的布局描述生成初稿虽然细节要调但至少结构是对的省去了我反复翻文档对照语法的时间。5.2 帮我发现没想到的边界情况AI有个好处是它不会想当然。有些边界情况我自己写的时候可能会忽略但AI在生成代码时会顺手处理掉。比如待办列表为空时显示什么、计时到零时如果用户正好在操作界面会不会冲突、存储读取失败时怎么降级——这些它都会给出处理分支。当然它给出的处理方式不一定符合我的预期但至少提醒了我这里有个情况要考虑。我经常是看着AI的代码想哦对这种情况我确实没想过。然后按自己的思路重新处理。5.3 调试时的思路启发遇到bug时我习惯把现象和报错信息丢给AI让它分析可能的原因。它给出的答案不一定对但经常能提供一些我没想到的排查方向。比如前面提到的真机白屏问题AI提示我可能是内存溢出让我去检查初始化时的对象创建数量这个方向是对的。不过要强调的是AI的排查建议只能当参考最终还是要靠自己在真机上验证。它有时候会给出一些听起来很有道理但实际上不适用于手表环境的建议比如建议我用某个Web API而那个API在手表JS引擎里根本不存在。5.4 AI coding的边界在哪里用了这几个周末我对AI coding的边界有了比较清晰的认识。它擅长的是生成结构化的样板代码、提供多种实现思路、处理常见的边界情况、根据报错给出排查方向。它不擅长的是理解特定平台的限制、把握业务语义的细节、做性能相关的取舍决策、真机调试。所以我的工作流是让AI生成初稿和思路我来做平台适配和业务修正真机测试和性能调优完全靠自己。这个分工下AI确实能提速但如果你指望它全自动搞定那在手表这种小众平台上一定会翻车。提示给AI的提示词里一定要把平台限制说清楚。比如这是运行在内存受限的手表上的JS应用没有DOM存储只有键值对接口把这些约束写进去它生成的代码质量会高很多。6. 踩过的坑和排查实录6.1 真机白屏内存溢出的排查这是最折腾的一个问题。模拟器里一切正常装到真机上打开就白屏没有任何报错。我一开始以为是打包配置的问题折腾了半天打包流程没用。后来把AI拉进来分析它提示可能是初始化时内存占用过高。我回头检查代码发现待办列表的初始化里我给每个列表项都创建了独立的视图对象而且一次性全创建了。待办少的时候没事待办一多内存直接爆。解决办法是列表项复用只创建屏幕可见数量的视图对象滚动时更新内容而不是新建对象。改完之后白屏问题消失。这个坑让我深刻理解了手表应用能省则省的原则。6.2 计时不准后台挂起的处理前面提过用累减法计时息屏再亮屏时间就对不上。这个问题的根源是手表系统会在应用进入后台后挂起定时器你的每秒减一根本不执行。改成时间戳差值法之后问题解决。这个改动很小但效果是决定性的。我后来把这个思路也应用到了休息计时上同样准确。6.3 震动不触发通知权限与后台限制番茄钟到点不震动这个问题的排查花了点时间。一开始我以为是震动API调用有问题单独写了个测试按钮发现震动是好的。那就说明是触发时机的问题——应用在后台时定时器被挂起了根本没执行到震动那行代码。解决办法就是前面说的双保险注册系统本地通知让系统在到点时唤醒。这里要注意注册通知时要申请相应权限而且不同系统版本对后台通知的限制不一样得实测。6.4 存储写入卡顿IO频率的控制批量勾选待办时界面卡顿一开始我以为是渲染性能问题优化了半天界面没效果。后来用日志打点发现卡顿发生在写存储的那一瞬间。原来我每次勾选都写一次存储连续勾选就是连续写手表存储IO扛不住。改成延迟合并写入后卡顿消失。这个优化思路其实很通用任何频繁的IO操作都应该考虑合并和延迟。问题现象排查方向根本原因解决方案真机白屏打包配置→内存占用初始化创建过多视图对象列表项复用计时不准定时器逻辑后台挂起导致累减失效改用时间戳差值震动不触发震动API→触发时机后台定时器被挂起系统通知兜底批量操作卡顿渲染性能→IO频率频繁写存储延迟合并写入6.5 几个容易被忽略的细节除了上面几个大坑还有些小细节值得记一笔。第一应用图标和名称要提前准备好合适尺寸的资源不然装到手表上显示会糊。第二首次启动时的引导页别做太复杂用户没耐心看我最后直接砍掉了引导页改成界面上用极简的提示文字。第三测试时一定要用真机模拟器的内存、性能、显示都跟真机有差距很多问题只有真机才暴露得出来。还有个经验每次改完代码先在模拟器上快速验证逻辑再装真机验证体验。模拟器适合调逻辑真机适合调体验两者分工明确效率最高。7. 一些关于AI辅助开发的个人体会这个项目做完我对AI coding的看法务实了很多。它不是魔法不能替你做决策也不能替你理解平台。但它确实是一个很好的加速器尤其是在你不熟悉的领域里它能帮你快速跨过入门门槛把精力集中在真正需要人判断的地方。我个人的经验是用AI coding做小项目最有效的模式是我定方向和约束它出初稿我来改。方向包括功能范围、技术选型、平台限制约束包括内存、存储、性能这些硬指标。把这些说清楚AI的输出质量会高一个档次。反过来如果你只是丢一句帮我写个番茄钟那它给你的东西大概率是不能直接用的。另外AI生成的代码一定要自己过一遍。不是不信任它而是它不理解你的具体场景。它写的每一行你都要问自己这行在我的设备上、我的使用场景下成立吗。这个习惯能帮你避开大部分坑。最后分享一个小技巧把AI当成一个会写代码但不懂你项目的同事。你会怎么跟这样的同事协作你会给他清晰的背景、明确的需求、具体的约束然后review他的产出。用这个心态去用AI coding效率和质量都会好很多。这个番茄待办应用我现在每天都在用虽然功能简单但胜在顺手。手表这东西一旦有了一个你真正需要的功能它就从吃灰的摆设变回了有用的工具。如果你手上也有闲置的智能手表不妨试试给它写点自己需要的小东西这个过程本身就挺有意思的。