Flutter、RN、KMP怎么选?我三个项目都试了一遍,聊点实际参数

🔑 关键词:Flutter, React Native, Kotlin Multiplatform, 跨平台框架, 移动端架构

📖 摘要:基于三个真实项目的包体积、冷启动、渲染性能数据,从个人维护角度对比 Flutter / RN / KMP 的优缺点和反主流观点。

先交代一下背景:我不是什么技术KOL,只是做过七年Android原生、后来被迫接触跨平台的普通人。2018年用React Native接手一个二手仓储App,维护到怀疑人生;2022年又用Flutter做了两款门店工具应用;2023年底开始用Kotlin Multiplatform(下面简称KMP)做一个带BLE硬件的配套产品,把iOS和Android共用的蓝牙解析、指令集还有数据库操作全塞进了一个shared模块。到今天三个项目一个已停运、一个还在迭代、一个刚上大版本。所以这篇文章不谈漂亮的架构图,只讲同一个小场景下肉眼可见的矛盾和坑。

图片

如果你只看社区评测,好像所有框架跑起来差距都不大。我们实际压测的硬件是Redmi K40(骁龙870),测试场景是扫描枪连续扫码、本地SQLite高频读写、RSA加密上传。同样的功能和UI层级,Flutter 3.22 release APK是18.3MB,其中libflutter.so大概占了8MB;RN 0.74使用Hermes和new architecture,加一些必须的Bridging之后是16.9MB;KMP只做共享逻辑,UI是原生Compose和SwiftUI,最终APK是11.7MB。冷启动从用户点击图标到看见主界面,Flutter平均1.8秒,RN平均2.2秒,KMP对应的原生方案大约1.2秒。也许你觉得几百毫秒无所谓,但那些店员一天要在后台杀App一百次,累积起来的体感绝不是图表上的零点几秒。

图片

再往深一点说渲染。Flutter在Android上用Impeller解决了部分卡顿,但它的WebView和视频层跟列表的混合合成依然会有些生硬,整个页面感觉隔了一层膜。RN的新架构用JSI撤掉了老旧的异步桥,可是真在这颗骁龙870上跑120Hz刷新率的滚动列表,一旦在JS线程里做繁重的state计算,帧时间会突然从8ms拉到15ms上下,体感就是偶尔顿一下。KMP因为UI是各平台原生写的,所以最坏帧耗时大约是Flutter的四分之一,代价是你得在学习Jetpack Compose之后再学一遍SwiftUI,同一套交互要写两次,而且两端的处理方式往往不完全一样。

图片

再说热门但容易被高估的功能:热重载。Flutter热重载的确无敌,改完一碰屏幕状态就更新了,但整个工程一旦引入第三方Native层,改动原生代码依然要冷编译。RN的Fast Refresh在大型项目里经常丢状态,比如你停在登录页,热重载完会回到首页,但登录态没了,还得重新走一遍验证码;Metro启动的时间长到可以喝口咖啡。KMP压根没有跨语言热重载,改共享逻辑就要重新打Framework,头两次你会崩溃,后来习惯了反而觉得踏实。实际来说,热重载影响的是开发早期的幸福感,不影响App后期寿命——这句话很多人不敢说。

图片

说说我的个人观点,甚至可能偏激:跨平台框架这些年拼命解决的是渲染一致性和开发效率,但决定App死活的根本不是UI。我曾见过太多项目死在状态管理失控、升级依赖链崩塌、需求来回改导致逻辑模块被耦合进View层这些事上。Flutter和RN强制你用一套代码同时管理UI和业务逻辑,感觉上很省,其实跨平台层变成了一个新的“技术债容器”。KMP本质上是一个反框架,它不负责UI,只把数据、网络、状态机等稳定核心抽取出来,让原生负责多变的界面。在我看来这种“被逼出来的整洁架构”才是框架能持续演化的关键,所以未来我更看好KMP和原生UI的组合,而不是大而全的跨平台SDK。

图片

生态也不得不说。Flutter在pub.dev上真的有不少老牌包维护跟不上,例如地图相关差不多要自己折腾截屏叠加,最后包体积又胖了2MB。RN的第三方库种类多但依赖链脆,经常因为一个gradle传递依赖让CI挂掉。KMP目前三方库还不丰富,常见的能力得拿moko或者直接调C++包装,适配工作有点繁琐。但值得注意的是,如果准备在移动端跑AI推理、用llama.cpp做端侧模型,KMP可以通过Cinterop直接调用C++,Flutter需要自己写一套ffi的壳,RN更麻烦,只能在原生层编译好后用bridge塞给JS。这是很多对比文章永远不会说到的点。

图片

所以,到底怎么选?纯MVP验证、团队全是JS背景,那RN或Expo可以快速上;产品以视觉呈现为核心、未来不太会深入底层计算并且你能忍受Dart某些奇奇怪怪的限制,Flutter是首选;如果目标是五年生命周期、要对接硬件、要上边缘AI,并且团队里至少有两三个对Kotlin或C++有敬畏心的人,那就放过你的原生UI层,认真考虑KMP。我自己的路线很土:先用Flutter做原型抢一波用户,验证之后不要犹豫,把核心逻辑用KMP重写,UI该用Compose用Compose,该用SwiftUI用SwiftUI。虽然写了双份UI,但你省下的是掉头发的全部过程。