大家好,我是老刘
最近看到一条新闻,红果已经成了第四大 App。短剧确实是时间黑洞,也是我为数不多能看进去的女频内容。
不过我看短剧有个习惯,碰到不感兴趣的桥段,就长按屏幕边缘加速,前几天让我按出了一个小 bug。
这个 bug 不复杂,却很适合拿来聊一个问题。为什么有些bug人和 AI 都容易犯?而响应式框架又能帮我们省掉哪类麻烦?
一个两倍速的小 bug
复现过程很简单。
长按屏幕边缘,开启临时两倍速播放。当前这一集播完,App 自动切到下一集,这时再松开手。
实际播放速度已经回到正常的一倍速,屏幕右下角的倍速按钮却仍然显示两倍速。
点开播放速度选择列表,里面的展示又是正常的。同一份播放速度,在两个界面里给出了两种答案。

这个 bug 和响应式编程有什么关系?
关系就在于,它是命令式 UI 开发中很典型的一类同步问题。
方案一,新增功能时漏掉一个同步点
先说明一下,下面几种实现只是老刘根据现象做的推测。我没有看过对应代码,也不确定它真实采用了哪种方案。
但这个推测过程,足够帮助我们理解问题是怎么出现的。
一种可能的流程是这样的。
长按屏幕边缘,开启临时两倍速播放。
用临时加速播放的悬浮信息,替换正常播放界面的悬浮信息。
因为整个悬浮展示都被换掉了,原有悬浮界面不需要修改,仍然保留一倍速的展示。
当前这一集播完后自动跳到下一集。为了提前缓冲,这里大概率会创建一个新的播放窗口。
由于用户一直没有松手,屏幕上仍然展示临时加速的悬浮信息。
新窗口建立时就是两倍速播放,所以新窗口自身的正常悬浮信息也是两倍速。
用户松开手,播放速度恢复正常。
代码关掉了临时加速的悬浮界面,换回正常悬浮界面,却漏掉了正常界面中倍速按钮的文字更新。
问题就在后面两步。
长按边缘加速,大概率是播放页面做完之后新增的功能。开发这个功能时,如果把主要注意力放在长按、松手和悬浮层切换上,确实可能没考虑到自动切到下一集的场景。
命令式 UI 允许开发者拿到某个控件,直接修改它的文字和状态。这样做很灵活,代价是每增加一个场景,都要人工检查一遍相关的同步点。
状态已经变了,界面却没有跟着变,bug 就这么出来了。
方案二,用观察者模式统一通知
在命令式编程的体系里,这个问题也有成熟的改进办法,观察者模式就是其中经典的一种。
播放器持有播放倍速数据,作为发布者。所有悬浮在播放器之上的信息展示界面,都作为这个数据的观察者。
不管是临时加速界面,还是正常播放界面,只要收到倍速变化的通知,就更新自身展示。
逻辑上看,只要大家严格遵循这套规则,问题就能解决。响应式 UI 框架的底层思路,也是这种状态通知机制。
那这套方案为什么还可能出bug?
因为规则需要人来维护,框架仍然保留着绕开规则直接修改 UI 的路径。
假设项目早期已经用了观察者模式,后来来了一位新同事,或者从其他部门转来一位同事,让他开发长按加速功能。
他可能不了解过去的开发约定,也可能根本没看到相关文档。
即使知道过去的约定可能也会觉得,临时加速只是一个独立悬浮层,不影响原来的界面,自然没必要修改原有界面的逻辑,直接修改界面播放速度就行。
每一种判断单独看都挺合理的,放到整个播放流程里就漏掉了一个同步点。
所以,写进文档的约定,要靠大家记得。做进框架的约束,才能在每次开发中持续发挥作用。
方案三,响应式框架怎么做
以 Flutter 为例,其实flutter解决这种隐患的思路非常简单,他压根儿没有给你提供直接修改界面元素的方法。
也就是说,你没有办法直接在某个界面元素上调用一个set方法,就更新这个界面元素。
Flutter更新界面元素的正规路径只有一条,就是状态管理。
在Flutter的哲学中,所有可变的数据都是状态。
而界面元素的更新只能绑定并监听状态的变化。
开发者更新界面元素唯一的路径就是给框架提供一个回调,当状态变化时,根据最新状态生成整个界面的回调方法。
换句话说,Flutter把观察者模式变成了更新UI的唯一路径。不仅仅是Flutter,其实所有的响应式开发框架的底层思路都是差不多的。
这样设计的结果就是,所有界面上的可变元素都一定要监听对应状态的变化。同时,只要这个数据状态产生了变化,所有相关的界面元素都会收到通知并进行更新。
这样就从根本上杜绝了前面提到的这种问题。
倍速状态是一倍,界面就按照一倍速生成。倍速状态变成两倍,相关界面就按照两倍速重新生成。
临时悬浮层和正常悬浮层如果读取同一份状态,松开手指时只需要把状态改回一倍速,相关界面就会按照各自的声明完成更新。
当然,Flutter 也不会自动消灭这类 bug。开发者依然可能设计错状态,也可能让两个页面读取不同的数据源。
它减少的是一类具体问题,状态已经修改,开发者却忘了手动修改某个控件。
响应式框架的价值在于少维护一些靠人记住的同步关系。
人类容易漏改的地方,AI 也容易漏
看到这里,可能有同学会问,这和 AI 编程有什么关系?
因为人类在命令式框架里容易犯的错,AI 同样可能犯。
老刘有个开源项目,代码全部由 AI 完成。我只负责确认需要什么功能,不负责具体修改代码。
前段时间,这个项目也出现过类似的同步问题。
我在 AI 供应商的 Provider 页面新增了一个 Provider,模型列表页面却没有同步看到这个新增项。
本质原因也是命令式 UI 框架下,有一处关联修改被漏掉了。
我的开发流程里,方案设计一般使用 Claude 5.5 Opus 或 Kimi K3,实际修改代码使用 DeepSeek V4.1 Flash。
Claude 5.5 Opus 在设计方案时,没有想到 Provider 的增删需要同步修改模型列表页。DeepSeek V4.1 Flash 真正写代码时,也没有发现这个遗漏。
但在我的 Flutter 项目中,使用同样的模型和 Agent,从来没碰到过类似问题。
这个样本不大,不能据此断定 Flutter 项目就不会出这种 bug。不过这个对比足够提醒我,框架提供的约束,对 AI 同样有效。
AI 生成代码时也会受上下文影响。需求里没有点明的页面,它可能没有主动检查。项目里存在多条 UI 更新路径,它也可能只改当前看到的那一条。
人容易漏掉的地方,AI 也可能漏。代码生成得越快,遗漏也可能越快地被写进项目。
AI 时代,老框架还有一层新价值
这篇文章没有打算推广 Flutter,也不打算神化 AI 编程。
老刘只是想用刷短剧和实际开发中碰到的场景,分享一个越来越明显的感受。
经过时间检验的框架,除了帮助人类写出更稳定的代码,也能帮助 AI 减少一些低级遗漏。
AI 时代,框架的约束正在变成质量管理的一部分。把正确的更新路径留得清楚一些,把随意绕行的空间收得窄一些,人类开发者和 AI 都能少踩几个坑。
而且人类留着这些口子可以方便写代码,对AI来说这种方便没有任何收益。
你在 AI 编程中遇到过这种"一个地方改了,另一个页面没跟上"的 bug 吗?欢迎评论区聊聊。
🤝 如果看到这里的同学对客户端或者Flutter开发感兴趣,欢迎联系老刘,我们互相学习。
🎁 私信免费领老刘整理的《Flutter开发手册》,覆盖90%应用开发场景。可以作为Flutter学习的知识地图。
💬 : laoliu_dev
📂 老刘也把自己历史文章整理在GitHub仓库里,方便大家查阅。