
网罗开发 (小红书、快手、视频号同名)
大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等方向。在移动端开发、鸿蒙开发、物联网、嵌入式、云原生、开源等领域有深厚造诣。
图书作者:《ESP32-C3 物联网工程开发实战》
图书作者:《SwiftUI 入门,进阶与实战》
超级个体:COC上海社区主理人
特约讲师:大学讲师,谷歌亚马逊分享嘉宾
科技博主:华为HDE/HDG
我的博客内容涵盖广泛,主要分享技术教程、Bug解决方案、开发工具使用、前沿科技资讯、产品评测与使用体验 。我特别关注云服务产品评测、AI 产品对比、开发板性能测试以及技术报告,同时也会提供产品优缺点分析、横向对比,并分享技术沙龙与行业大会的参会体验。我的目标是为读者提供有深度、有实用价值的技术洞察与分析。
展菲:您的前沿技术领航员
👋 大家好,我是展菲!
📱 全网搜索"展菲",即可纵览我在各大平台的知识足迹。
📣 公众号"Swift社区",每周定时推送干货满满的技术长文,从新兴框架的剖析到运维实战的复盘,助您技术进阶之路畅通无阻。
💬 微信端添加好友"fzhanfei",与我直接交流,不管是项目瓶颈的求助,还是行业趋势的探讨,随时畅所欲言。
📅 最新动态:2025 年 3 月 17 日
快来加入技术社区,一起挖掘技术的无限潜能,携手迈向数字化新征程!
文章目录
-
- 前言
- [先从一张"脑补图"理解三种 UI 渲染模型](#先从一张“脑补图”理解三种 UI 渲染模型)
-
- [Flutter 的渲染模型](#Flutter 的渲染模型)
- [React Native 的渲染模型](#React Native 的渲染模型)
- [iOS 原生(UIKit / SwiftUI)](#iOS 原生(UIKit / SwiftUI))
- [Flutter 为什么滚动特别稳?](#Flutter 为什么滚动特别稳?)
-
- [Flutter 的滚动是"纯本地逻辑"](#Flutter 的滚动是“纯本地逻辑”)
- [Flutter 为什么首屏反而偏慢?](#Flutter 为什么首屏反而偏慢?)
- [RN 在复杂场景下为什么容易掉帧?](#RN 在复杂场景下为什么容易掉帧?)
-
- [一个最典型的 RN 动画场景](#一个最典型的 RN 动画场景)
- [useNativeDriver 是"止痛药",不是解药](#useNativeDriver 是“止痛药”,不是解药)
- [Web / RN 为什么对"原生一致性"这么敏感?](#Web / RN 为什么对“原生一致性”这么敏感?)
-
- [Flutter 为什么反而"样式一致"?](#Flutter 为什么反而“样式一致”?)
- [iOS 原生的性能天花板在哪里?](#iOS 原生的性能天花板在哪里?)
- 三种方案放在真实项目里的取舍
- 总结
前言
如果你同时写过 Flutter、RN 和 iOS 原生,大概率会有一种直觉:
- Flutter 滚动是真的稳
- RN 页面一复杂就开始抖
- iOS 原生性能最好,但人力成本也是真的高
问题是------
为什么会这样?
不是因为语言,不是因为团队水平,而是三者从 UI 渲染这一步开始,走的就是完全不同的路。
这篇文章我们就从「UI 是怎么画出来的」这个最底层的点出发,把三种方案真正的差异讲清楚。
先从一张"脑补图"理解三种 UI 渲染模型
我们先不急着看代码,先把三种方案在脑子里"画"出来。
Flutter 的渲染模型
Dart Widget Tree
↓
RenderObject Tree
↓
Skia
↓
GPU
特点只有一句话:
Flutter 不使用系统原生 UI 控件,而是自己画。
按钮、列表、文本、动画,本质都是 Skia 在一块画布上画出来的。
React Native 的渲染模型
JS (React)
↓
Bridge
↓
Native UI View (UIKit / Android View)
RN 的核心思路是:
UI 还是原生的,但"怎么组合 UI"交给 JS。
问题也恰恰出在这个 Bridge 上。
iOS 原生(UIKit / SwiftUI)
Swift / ObjC
↓
UIKit / SwiftUI
↓
Core Animation
↓
GPU
没有跨语言,没有中间层,
系统怎么设计,开发者就怎么用。
如果你只记住一句话:
- Flutter:自己画
- RN:JS 指挥原生画
- iOS:直接画
后面所有性能差异,其实都能推出来。
Flutter 为什么滚动特别稳?
很多人第一次写 Flutter ListView,都会有点震惊:
怎么随便写写,滚动就这么顺?
原因其实非常直接。
Flutter 的滚动是"纯本地逻辑"
在 Flutter 里,一个滚动列表大概是这样:
dart
ListView.builder(
itemCount: 1000,
itemBuilder: (context, index) {
return ListTile(
title: Text('Item $index'),
);
},
);
关键点不在 Widget,而在底层:
- 手势处理在 Dart 层
- 滚动计算在 Dart 层
- 帧同步直接对接 Skia
整个滚动过程,不需要跨语言通信。
这意味着什么?
意味着:
- 没有 JS 卡顿影响滚动
- 没有 Bridge 延迟
- 掉帧风险极低
Flutter 为什么首屏反而偏慢?
但 Flutter 也不是没有代价。
首屏慢,原因通常有三类:
- Dart VM / AOT 启动
- Widget Tree 构建成本
- Skia Pipeline 初始化
你可以理解为:
Flutter 是"先把画室搭好,再开始画"。
一旦跑起来,后面就很稳;
但启动那一下,成本是实打实存在的。
RN 在复杂场景下为什么容易掉帧?
RN 的问题,其实不是"慢",而是不可控。
一个最典型的 RN 动画场景
jsx
Animated.timing(this.state.x, {
toValue: 100,
duration: 300,
useNativeDriver: false,
}).start();
如果 useNativeDriver: false:
- 每一帧动画
- 都需要 JS 计算
- 再通过 Bridge 通知原生更新 View
这意味着什么?
16ms 内:
JS 算 → Bridge → Native → Render
只要其中任意一环慢一点:
- JS 被阻塞
- Bridge 堆积
- 原生掉帧
你看到的结果就是:
动画一卡一卡的,但你很难定位是哪一层的问题。
useNativeDriver 是"止痛药",不是解药
开启 native driver 后,动画会交给原生跑:
jsx
useNativeDriver: true
但代价是:
- 只能用 transform / opacity
- 无法驱动 layout
- 复杂交互依然要回到 JS
这也是为什么 RN 在:
- 复杂列表联动
- 大量手势动画
- 高并发 UI 更新
这些场景下,很容易到瓶颈。
Web / RN 为什么对"原生一致性"这么敏感?
这一点,做过多端适配的人体会会非常深。
RN 和 Web 的 UI,本质是:
对系统控件的"再封装"。
这会带来几个现实问题:
- iOS 和 Android 原生控件行为不同
- 系统版本升级会影响样式
- 某些 UI bug 只在某个平台出现
你明明写的是一套 JS / CSS,
但最后却要:
- iOS 单独 patch
- Android 单独 hack
Flutter 为什么反而"样式一致"?
因为 Flutter 根本没用系统控件。
- 按钮自己画
- 文本自己排
- 阴影、圆角全自己算
代价是包体和启动时间,
收益是:
UI 行为在所有平台几乎一致。
iOS 原生的性能天花板在哪里?
从纯性能角度看:
iOS 原生几乎没有对手。
一个典型的 UIKit 列表:
swift
class ViewController: UIViewController, UITableViewDataSource {
func tableView(_ tableView: UITableView,
numberOfRowsInSection section: Int) -> Int {
return 1000
}
func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = "Row \(indexPath.row)"
return cell
}
}
系统级优化包括:
- 视图复用
- Core Animation 合成
- RunLoop 调度
这些都是 Flutter 和 RN 无法直接复刻的系统能力。
那为什么大家还在做跨端?
答案只有一个:人力成本。
- 三端三套代码
- 三个技术栈
- 三种问题模型
在业务快速迭代期,这个成本非常高。
所以真实世界的选择往往是:
- 极致体验 → 原生
- 体验和效率平衡 → Flutter
- 强动态 / 业务驱动 → RN / Web
三种方案放在真实项目里的取舍
如果你站在一个负责人视角,而不是"技术选型洁癖",结论通常会是这样:
- 强动画、重交互、长期维护:Flutter
- 快速试错、动态下发、业务变化快:RN
- 系统级能力、极致性能、平台特性:iOS 原生
没有银弹,只有边界。
总结
很多技术争论,本质不是对错,而是上下文不同。
Flutter、RN、iOS 原生三套方案:
- 起点不同
- 设计目标不同
- 解决的问题也不同
真正成熟的判断标准只有一个:
这个项目最怕什么?
- 怕卡顿 → 远离 Bridge
- 怕成本 → 拥抱跨端
- 怕体验 → 回归原生
想清楚这个问题,选型其实就没那么纠结了。