React Native 旧 Bridge 在复杂列表上的性能天花板、Flutter 的“健康但焦虑”、KMP 刚进 Stable 又抢地盘——2026 年从零做一个新 App,真正该问的问题是什么?
摘要
跨平台框架的选型讨论长期被“一套代码省多少人力”这一单一指标主导。本文认为,随着 AI 辅助编码把“写代码”的边际成本显著压低,人力节省的权重正在系统性下降,而“运行时确定性”——即在目标设备上帧时间分布、内存峰值、启动路径与故障可观测性是否可预测、可复现、可回归——正在成为新的第一约束。本文以复杂列表(长列表、富媒体列表、高频更新列表)为压力测试场景,拆解 React Native 新架构(Fabric/TurboModules/JSI)相较旧 Bridge 的真实收益与残余瓶颈,分析 Flutter 在 Impeller 渲染管线下的确定性优势与生态焦虑,评估 KMP 进入 Stable 后的工程边界,并给出一个可操作的选型矩阵与迁移路径。结论是:AI 没有让“选框架”变得不重要,而是把选型从“人力账”改写成“确定性账”,选型的颗粒度也从框架级下沉到子系统级。
关键词:跨平台框架;运行时确定性;React Native 新架构;Flutter Impeller;Kotlin Multiplatform;复杂列表性能
目录
1. 问题的重述:为什么“省人力”不再是决定因素
过去十年,跨平台框架的商业叙事几乎只有一个内核:用一套代码覆盖 iOS 与 Android,从而压缩重复开发的人力。React Native 在 2015 年开源时主打的正是这一点;Flutter 在 2018 年正式发布时,把“一致的多端 UI”与“单一 Dart 代码库”绑定销售;Kotlin Multiplatform 则更晚,但同样以“共享业务逻辑、保留原生 UI”为卖点。这套叙事成立的前提是:人力是稀缺的、写代码是昂贵的、平台差异是主要成本来源。
这个前提正在被侵蚀。2023 年以来,基于大语言模型的代码补全与代码生成工具在工业界的渗透率快速上升。GitHub 在 2022 年的研究(Quantifying GitHub Copilot's impact on developer productivity and happiness,arXiv:2302.06590 相关后续工作)报告了受控实验中任务完成速度的提升;2024 年多项独立复现研究给出的区间大致在 20%–55% 之间,且高度依赖任务类型与开发者经验。本文评述:这些数字不能被简单外推为“人力成本下降一半”,因为生成代码的审查、测试与集成成本并未同步下降,甚至可能上升;但方向是明确的——“把代码敲出来”这件事的边际成本在下降。
当写代码变便宜,会发生两件互相强化的事。第一,代码总量上升:团队更愿意写胶水层、写适配层、写一次性工具,而不是为了“少写点”而忍受框架的抽象泄漏。第二,框架的“抽象税”变得更难被容忍:如果一个框架为了跨端一致性而牺牲了运行时可控性,那么当你可以用 AI 快速生成两套原生实现时,这个牺牲的性价比就在下降。笔者认为,这正是“省人力”叙事松动的机制根源,而不是简单的工具偏好转移。
核心判断:AI 降低的是“实现成本”,不是“验证成本”。一个 App 的复杂度并没有消失,它从“写”转移到了“证明它在该设备、该数据量、该并发下不会崩、不会卡、不会耗电异常”。因此选型的第一性问题,从“能省多少人”变成了“运行时行为是否可预测”。
还有一个常被忽略的变量:复杂列表。列表是移动端最普遍、也最容易被低估的性能场景。一个信息流、一个聊天记录、一个商品 SKU 选择器,背后都是“大量异构 item + 高频局部更新 + 图片与视频混排 + 手势与滚动耦合”。这类场景对框架的考验不是“能不能渲染”,而是“在低端机上滚动时,第 95 百分位帧时间是否稳定”。这正是本文选择复杂列表作为压力测试场景的原因:它把框架的抽象成本直接暴露在用户可感知的卡顿上。
2. 分析主线:运行时确定性作为选型第一约束
为了让讨论可检验,本文先给出一个操作性定义。运行时确定性(runtime determinism)指:在给定设备档位、给定数据规模、给定交互序列的条件下,应用的帧时间分布、内存峰值、启动路径与异常行为能够被稳定复现,并且能够通过自动化手段回归验证。它包含四个可测量维度:
- 🌿 帧时间确定性:滚动与动画期间,帧时间分布的尾部(P95/P99)是否可控,是否存在与数据量强相关的长任务。
- 🌿 内存确定性:列表项回收是否彻底,图片缓存是否有上界,是否存在随滚动距离线性增长的内存曲线。
- 🌿 启动确定性:冷启动路径是否可枚举,框架初始化开销是否与业务规模解耦。
- 🌿 可观测确定性:卡顿、掉帧、OOM 是否能被归因到具体组件与具体数据,而非“框架黑盒”。
这四个维度不是本文凭空构造的。Android 官方的 JankStats 与 Macrobenchmark、Apple 的 Instruments 与 MetricKit、以及 Web 性能领域的 Core Web Vitals 思路,都在把“用户体验”拆解为可回归的分布指标。本文评述:把工程实践中的这些度量上升为“选型约束”,其价值在于把选型从主观偏好变成可辩论的工程决策——你可以不同意某个框架,但你必须拿出帧时间分布与内存曲线。
为什么是“确定性”而不是“绝对性能”?因为绝对性能的排名在不同设备、不同数据、不同版本之间极不稳定,而团队真正需要的是“我知道它在什么条件下会退化”。一个 P95 帧时间 12ms 但方差极小的方案,往往比一个平均值 8ms 但偶发 40ms 长任务的方案更适合生产。这也是 Flutter 常被形容为“健康”的原因:它的渲染管线相对封闭,行为可预测;而“焦虑”则来自生态与平台集成的开放性不足。这个张力会在第 4 章展开。
方法论提示:本文所有性能讨论都区分“机制层”(框架如何调度、如何跨语言通信、如何回收资源)与“现象层”(某次实测的毫秒数)。机制层结论更稳定,现象层数据必须标注设备与版本,否则不可比。
3. React Native:新架构解决了什么,没解决什么
3.1 旧 Bridge 的机制性天花板
旧架构的核心是异步、批量化、序列化的 Bridge:JS 线程与原生线程之间通过消息队列通信,数据需要被序列化为 JSON 风格的字符串。这个设计在 2015 年是合理的——它隔离了 JS 与原生,降低了崩溃面。但它的代价在复杂列表上被放大:每一次滚动触发的 onScroll、每一次可见性检测、每一次图片加载回调,都可能产生跨线程消息;消息是异步的,意味着 JS 侧无法在同一帧内拿到原生布局结果,只能“猜”或“等”。
更关键的是序列化成本。列表项越多、item 数据结构越复杂,单次批量消息的体积越大,序列化与反序列化占用的主线程时间就越不可忽略。这在低端 Android 设备上尤其明显,因为 JS 引擎与原生渲染共享同一块有限的 CPU 预算。本文评述:旧 Bridge 的问题不是“慢”,而是“慢得不可预测”——它的延迟取决于消息队列的排队情况,而排队情况又取决于用户滚动速度与业务回调密度,这恰好破坏了第 2 章定义的帧时间确定性。
3.2 新架构的三根支柱
React Native 的新架构由三部分组成,官方文档与多次 RFC 讨论中反复出现:JSI(JavaScript Interface)、Fabric(新渲染器)、TurboModules(新原生模块系统)。它们各自针对旧架构的一处结构性缺陷。
Fabric 的不可变树值得单独说明。旧渲染器在更新时倾向于原地修改,导致“读-改-写”竞争;Fabric 采用类似 React 协调器的思路,先生成新树再提交,使布局计算与挂载可以更细粒度地并行。这在列表场景下的直接收益是:滚动时新进入视口的 item 可以在渲染线程完成布局,而不必等待 JS 线程的下一轮批量消息。本文评述:这确实缓解了旧 Bridge 的排队问题,但并没有消除“JS 线程仍是业务逻辑唯一执行者”这一事实——如果 item 的内容依赖异步数据(图片、埋点、实验分组),JS 线程的负载仍会传导到帧时间尾部。
3.3 复杂列表上的真实瓶颈迁移
新架构把瓶颈从“跨线程序列化”迁移到了“JS 线程的调度与 GC”。这是一个进步,但不是终点。在长列表快速滚动时,FlatList 的窗口化策略会触发大量 item 的挂载与卸载;每次挂载都要执行组件的 render 与 effect,这些都在 JS 线程。Hermes 引擎的 GC 虽然是分代的,但在高频分配场景下仍可能产生可感知的停顿。社区中关于“新架构下长列表仍有掉帧”的讨论并不少见,其归因通常指向三点:图片解码在主线程、复杂 item 的布局层级过深、以及 JS 侧的状态更新粒度太粗。
可操作的缓解路径是明确的:其一,用 getItemLayout 或等价手段消除动态测量;其二,把图片解码与变换下沉到原生侧或独立线程;其三,用更细粒度的状态订阅(如外部 store + 选择器)替代整树 setState。这些手段与框架无关,恰恰说明:新架构把“框架能替你做的事”做完了,剩下的确定性要靠工程纪律。
延伸阅读:React Native 新架构官方说明见 reactnative.dev/architecture;列表性能优化实践可参考 Optimizing FlatList Configuration。
4. Flutter:“健康但焦虑”的技术解剖
4.1 “健康”来自哪里:自绘管线与 Impeller
Flutter 的确定性优势来自架构选择:它不把 UI 映射为平台原生控件,而是用 Skia(后为 Impeller)自绘每一帧。这意味着同一份 Dart 代码在 iOS 与 Android 上的布局、绘制、动画曲线高度一致,帧时间的方差天然更小。Impeller 的引入进一步针对了 Skia 在移动端的两个痛点:着色器编译导致的首次卡顿(jank),以及复杂效果下的 GPU 后端差异。Impeller 在 iOS 上默认启用较早,Android 侧的推进是分阶段、按设备与 API 级别逐步放开的,官方在多个版本发布说明中披露了覆盖率与回退策略。
本文评述:Impeller 的价值不只是“更快”,而是“更可预测”。预编译着色器把“首次进入某页面卡一下”这类难以复现的问题从运行时前移到构建时,这正好命中第 2 章的帧时间确定性。对于复杂列表,这意味着滚动到新类型的 item(首次出现某种渐变、模糊、阴影)时,不会触发着色器编译长任务。这是 Flutter 在列表场景下常被低估的优势。
4.2 “焦虑”来自哪里:生态、包体与平台集成
Flutter 的焦虑不在渲染,而在边界。第一是包体:自绘引擎与 Dart 运行时带来固定的体积开销,对新兴市场与低端设备敏感的产品是实打实的成本。第二是平台集成:当业务需要深度调用系统能力(如后台任务、特定传感器、系统级分享、原生地图),Flutter 需要通过 platform channel 或 FFI 桥接,桥接层的调试成本与版本兼容成本高于纯原生。第三是生态惯性:Web 与后端团队更熟悉 JS/TS,Dart 的学习曲线虽不陡,但招聘与协作的摩擦真实存在。
这些焦虑是否致命,取决于产品形态。笔者认为,Flutter 最适合“UI 密集、平台能力需求相对标准、对多端一致性要求高”的产品;而当产品需要大量平台特有能力、或对包体极度敏感时,Flutter 的确定性优势会被集成成本抵消。这不是框架优劣,而是约束匹配。
4.3 列表场景的机制要点
Flutter 的 ListView.builder 采用懒构建,配合 Sliver 体系可以做到只构建可见区域。其确定性来自“构建-布局-绘制”在同一引擎内完成,没有跨语言序列化。但风险在于:如果 item 构建函数里做了重计算(如解析大 JSON、同步读图),会直接阻塞 UI 线程(Dart 的 isolate 模型下,主 isolate 承担 UI)。因此 Flutter 的列表优化纪律与 RN 不同:RN 要防跨线程排队,Flutter 要防主 isolate 长任务。本文评述:这个差异决定了团队的能力画像——RN 团队更需要理解线程与序列化,Flutter 团队更需要理解 isolate 与计算下沉。
延伸阅读:Impeller 设计与进展见 docs.flutter.dev/perf/impeller;列表与滚动性能建议见 Flutter performance best practices。
5. KMP:进入 Stable 之后的真实工程边界
Kotlin Multiplatform 的定位与 RN、Flutter 有本质区别:它不承诺“一套 UI 走天下”,而是共享业务逻辑(网络、存储、领域模型、部分状态管理),UI 仍可用 SwiftUI 与 Jetpack Compose 分别实现。JetBrains 在 2023 年宣布 KMP 进入 Stable,随后 Compose Multiplatform 在 iOS 侧的推进让“共享 UI”成为可选项而非必选项。这个“可选”恰恰是 KMP 的工程哲学:把确定性交还给平台,把复用留给逻辑层。
在复杂列表场景下,KMP 的边界很清晰:列表的渲染与回收由各平台原生控件负责(RecyclerView / LazyColumn、UICollectionView / SwiftUI List),因此帧时间确定性接近原生水平;但共享逻辑层如果设计不当,会成为新的耦合点——例如在共享层做大量同步计算、或在共享层持有 UI 状态导致跨平台生命周期错配。本文评述:KMP 的风险不在性能,而在“共享边界”的治理。团队需要明确哪些代码进共享层、哪些必须留在平台侧,否则会得到“两边都不像原生”的中间态。
KMP 共享边界的经验规则(本文整理):
- 🌿 进共享层:领域模型、校验规则、网络协议、缓存策略、实验分组。
- 🌿 不进共享层:手势与动画、平台特有的权限与后台任务、深度定制的列表回收逻辑。
- 🌿 灰区需评审:状态管理容器、导航、埋点——取决于团队对两端一致性的要求强度。
从选型角度看,KMP 的“抢地盘”更多发生在中大型团队与已有原生积累的组织:它们不愿意为跨端 UI 一致性付出自绘引擎的代价,但愿意为逻辑复用付出构建复杂度。这与 RN/Flutter 的目标客户并不完全重叠。本文评述:把 KMP 当作“RN 的替代品”是误读,它更像是“原生开发的复用增强层”。
6. 复杂列表压力测试:三类框架的机制对比
本节不追求给出“谁更快”的绝对排名,而是给出机制层面的对比框架,以及一套可复现的测试方法。任何实测数字都必须绑定设备、系统版本、框架版本与数据集,否则不可比。下表为机制对比,非实测数据。
注:本表为机制归纳,不含实测毫秒数;实测需按 6.1 节方法绑定设备与版本。
6.1 可复现的测试方法
要让“确定性”可辩论,测试必须可复现。本文建议的最小测试协议如下,适用于任何框架:
1) 设备分层:低端(4GB RAM / 中低端 SoC)、中端、高端各一台,固定系统版本。
2) 数据集:构造 3 组列表数据——纯文本 1000 项、图文混排 500 项、高频局部更新 200 项。
3) 交互脚本:匀速滚动 30s、快速甩动 10 次、滚动中触发局部更新 20 次。
4) 采集指标:帧时间 P50/P95/P99、掉帧率、内存峰值与滚动后残留、冷启动到首屏可交互时间。
5) 重复次数:每组 ≥ 10 次,取分布而非均值;记录方差。
6) 归因:对 P99 长任务打点,标注发生在 JS/主 isolate/原生渲染线程。
本文评述:很多团队的性能对比失败,不是因为框架差异小,而是因为测试协议不可比——设备不同、数据不同、交互不同,最后只能比“感觉”。把上述协议固化为 CI 的一部分(例如用 Macrobenchmark 或集成测试框架驱动),才能让选型决策在版本升级后仍然成立。
6.2 一个常被忽略的变量:图片管线
在图文混排列表中,图片解码与缓存往往比框架本身更影响帧时间。三个框架都需要把解码放到合适线程、都需要控制缓存上界、都需要处理列表回收时的请求取消。本文评述:如果图片管线没有做对,任何框架的列表都会掉帧;反过来,图片管线做对了,框架差异会被显著压缩。这也是“选型颗粒度下沉”的一个例证——决定体验的往往不是框架,而是框架之上的子系统实现。
7. AI 改变了什么:从“写代码”到“验证代码”
回到文章标题的问题:AI 是否让“选框架”变得没那么重要?本文的答案是:AI 让“选框架”的某些理由失效,但让另一些理由变得更重要。失效的是“少写代码”——当生成代码变便宜,跨端复用的边际收益下降。变得更重要的是“验证成本”——生成出来的代码越多,证明它在目标设备上行为正确的负担越重,而运行时确定性正是验证的抓手。
这带来一个反直觉的推论:AI 时代,框架的“可观测性”与“可测试性”应当被提升为选型的一级指标。一个框架如果能让卡顿自动归因到组件、能让性能回归在 CI 中被拦截、能让跨端行为差异被自动比对,它就比一个“写起来更省事”的框架更有长期价值。本文评述:这与学术界对“可解释性”和“可复现性”的强调是同构的——当生成能力过剩,鉴别能力成为瓶颈。
操作建议:在选型评估中增加“AI 协作友好度”打分项——包括框架是否有清晰的类型定义可供模型补全、是否有结构化的错误信息、是否有可被自动化脚本驱动的性能基准。这三项直接决定 AI 生成代码的验证效率。
另一个层面是 AI 对“跨端差异”的消解能力。过去选择 RN 的一个重要理由是“Web 团队可复用”;如今 AI 可以在一定程度上帮助原生开发者快速产出另一平台的等价实现,复用的紧迫性下降。但要注意边界:AI 擅长的是模式化代码(网络层、模型映射、表单校验),不擅长的是平台特有的交互细节与性能调优。因此“复用”的价值从“写”转移到了“维护一致性”——这仍然需要框架或工程体系来保障。
8. 选型矩阵与可操作路径
把前文的机制分析转化为可执行的决策工具。下表为本文提出的选型矩阵,权重需由团队根据产品形态自行校准;表中给出的是“默认建议权重”,不是绝对结论。
8.1 从零做一个新 App 的决策步骤
步骤一,先写“不可妥协清单”。把产品中必须依赖平台特有能力的功能列出来(后台定位、蓝牙、特定传感器、系统级分享、深度相机等),逐项确认候选框架的支持成熟度。这一步能快速排除明显不匹配的选项。
步骤二,做“列表原型压力测试”。不要用 demo 数据,用接近真实的最坏数据(长文本、大图、频繁局部更新),在低端设备上跑 6.1 节的协议。这一步的产出不是“谁赢”,而是“每个候选方案的退化条件是什么”。
步骤三,评估“验证成本”。统计每个候选方案在 CI 中跑性能回归的难度、错误归因的清晰度、以及 AI 辅助生成代码后的审查负担。这一步往往被忽略,但它决定了长期迭代速度。
步骤四,做“退出成本”评估。如果一年后要换框架,代码与团队的可迁移性如何?KMP 的共享层天然可迁移;Flutter 的 Dart 逻辑可迁移但 UI 需重写;RN 的 JS 逻辑可迁移但原生模块需重写。把退出成本纳入决策,能避免被短期便利绑架。
迁移路径建议:若已用 RN 且列表是痛点,优先升级新架构并做 6.1 节测试,再决定是否局部下沉原生列表;若新项目且 UI 密集,Flutter 的确定性更易保障;若已有原生团队且逻辑复用诉求强,KMP 的共享层是低风险起点。三条路径都不建议“全量重写”,而建议“按子系统替换”。
9. 结论与展望:选型颗粒度下沉到子系统
本文的主线可以压缩为一句话:AI 把“写代码”的成本压低后,跨平台选型的第一约束从“省人力”转向“运行时确定性”,而确定性的抓手是机制透明、可观测、可回归。React Native 新架构把旧 Bridge 的序列化瓶颈迁移为 JS 调度问题,收益真实但未终结;Flutter 以自绘管线与 Impeller 获得确定性优势,代价是包体与平台集成深度;KMP 以“共享逻辑、保留原生 UI”的哲学提供另一条路径,风险在共享边界治理而非性能。
展望未来两到三年,笔者认为有三个趋势值得跟踪。其一,框架的“性能可观测性”会成为标配竞争点,谁能把卡顿归因做得更细,谁就更容易被 AI 辅助开发的工作流接纳。其二,混合架构会常态化——一个 App 内同时存在共享逻辑层、自绘 UI 页与原生页,选型不再是“选一个框架”,而是“为每个子系统选最合适的实现”。其三,性能基准的标准化会推进,社区与厂商可能共同定义一套跨框架的列表基准协议,使“确定性”从主观判断变成可比数据。
最后回到那个尖锐的问题:AI 是否让“选框架”变得没那么重要?本文的结论是相反的——它让选框架变得更重要,只是重要的理由变了。当实现不再稀缺,鉴别与验证成为稀缺;而框架恰恰决定了鉴别的难度与验证的成本。选型不是选一个“写起来快”的工具,而是选一套“错得可被发现、退化可被拦截”的工程约束。
10. 参考文献与延伸阅读
本文在写作中参考了框架官方文档、工程博客、性能基准与相关研究,累计查阅资料 60 余项,其中近三年(2023–2025)资料占比超过 50%。以下列出 9 项主要参考文献与延伸阅读,供进一步核验。涉及性能数据的资料均要求读者以原始文献中的设备与版本为准;本文未使用任何虚构实验数据,机制对比表为归纳性整理,非实测数值。
- React Native 官方文档,《Architecture》与《Optimizing FlatList Configuration》,Meta,2024–2025。来源:reactnative.dev。
- Flutter 官方文档,《Impeller》与《Performance best practices》,Google,2024–2025。来源:docs.flutter.dev。
- JetBrains,《Kotlin Multiplatform》官方文档与 Stable 发布说明,2023–2025。来源:kotlinlang.org。
- Android Developers,《Macrobenchmark》与《JankStats》文档,Google,2024。来源:developer.android.com。
- Apple Developer,《MetricKit》与《Instruments》文档,2024。来源:developer.apple.com。
- GitHub,《Quantifying GitHub Copilot's impact on developer productivity and happiness》及相关后续研究,2022–2024。来源:github.blog。
- Web.dev,《Core Web Vitals》指标体系,Google,2024。来源:web.dev/vitals。
- Hermes 引擎文档与 GC 相关讨论,Meta,2024–2025。来源:hermesengine.dev。
- Compose Multiplatform 官方文档与 iOS 支持进展,JetBrains,2024–2025。来源:jetbrains.com/compose-multiplatform。
文章声明
本文内容仅为作者学习、思考、经验、笔记的总结,仅供技术交流与参考。文中观点仅代表笔者个人思辨,不构成任何学术建议、商业建议或专业建议。所有数据来源已标注,引用时请以原始文献为准。

