从双端开发到跨平台实践:我的React Native和Flutter对比之路
开篇:为什么选择聊这个话题?

作为在一家中型互联网公司做移动开发的开发者,过去三年里我经历了从原生 Android/iOS 双端开发,到逐步转向跨平台技术栈的全过程。最开始,我对“一次编写,处处运行”的口号是持怀疑态度的;但随着项目需求越来越快、人力成本越来越高,团队也开始尝试用更高效的方案去交付。
今天我想以第一人称的角度,结合我们最近一个 App 的实际开发经历,聊聊我在 React Native 和 Flutter 上踩过的坑、做出的选择,以及最终落地后的经验和建议。
问题描述:双端维护的成本太高了

事情要从去年的一次紧急项目说起。
我们当时接到一个内部孵化项目的需求,要做一个面向企业员工的轻量级协作工具。时间紧、任务重,产品希望两周出 MVP,然后快速迭代上线。我们团队一共四个人,两个 Android、两个 iOS,原本打算并行开发。
结果:
- 功能设计上稍有不一致,导致界面展示不同;
- 后台接口变更频繁,两端代码都要改;
- UI 适配差异多,特别是 iPad Pro 和 iPhone 13 的布局;
- 发布流程繁琐,iOS 提审被拒两次,Android 因权限弹窗误触发下架了一天。
最夸张的是,有一次产品经理临时改了按钮颜色,我们在 Android 和 iOS 上分别花了两个小时才搞定……那一刻我就觉得,这种纯原生开发的方式,已经不太适合现在这种快速试错的节奏。
于是我们决定:这次新项目,直接上跨平台开发框架试试看。
解决方案:选哪个框架?React Native 还是 Flutter?

我们先做了调研,重点比较了 React Native(RN) 和 Flutter 两个主流方案:
| 维度 | React Native | Flutter |
|---|---|---|
| 学习曲线 | JS 基础 + JSX 熟悉的人容易上手 | Dart 是一门相对冷门的语言,但结构清晰 |
| 性能表现 | 桥接机制影响性能,复杂动画略卡顿 | 自带 Skia 引擎渲染,UI 流畅性高 |
| 包体积 | 小,接近原生 | 相对较大(不过优化后也还可以接受) |
| 插件生态 | 第三方插件丰富,但质量参差不齐 | 官方支持好,但社区不如 RN 成熟 |
| 原生混编 | 支持混写原生代码 | 需要写 Dart/Platform Channel,复杂度略高 |
| UI 一致性 | 渲染依赖原生组件,风格可能不统一 | 自绘引擎,高度定制化,统一性强 |
综合考虑我们团队的技术背景:
- 两名开发有前端经验
- 对 UI 样式要求较高
- 需要快速原型验证,后期再接入部分原生模块
最终选择了:Flutter
虽然 Dart 是陌生的,但 Flutter 的高性能和 UI 控制力让我们更放心,尤其是在后续想做一些酷炫动效时,它确实比 RN 更有优势。
代码实践:从零搭建 Flutter 项目

我们的项目叫「TeamLink」,是一个类似 Slack 的轻量级协作 App,包含聊天、消息通知、联系人、简单任务等功能。
初始化项目
flutter create team_link_app
Flutter CLI 默认会生成 Android/iOS 两个平台的基础工程目录,非常方便。
主页面结构
我们采用了 BottomNavigationBar 做主 Tab 导航:
class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
int _currentIndex = 0;
final List<Widget> _pages = [
ChatListPage(),
ContactPage(),
TaskPage(),
];
void _onItemTapped(int index) {
setState(() {
_currentIndex = index;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: _pages[_currentIndex],
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(icon: Icon(Icons.chat), label: '消息'),
BottomNavigationBarItem(icon: Icon(Icons.people), label: '联系人'),
BottomNavigationBarItem(icon: Icon(Icons.task_alt), label: '任务'),
],
currentIndex: _currentIndex,
selectedItemColor: Colors.blue,
onTap: _onItemTapped,
),
);
}
}
这段代码很简单,但可以快速跑起来。配合 Navigator.push 我们轻松实现了页面跳转。
数据请求与状态管理
由于项目不算复杂,我们没有一开始就引入 Redux 或 Bloc 等状态管理库,而是采用 Provider + ViewModel 模式来组织数据层:
class UserViewModel with ChangeNotifier {
bool _loading = false;
UserModel? _user;
bool get loading => _loading;
UserModel? get user => _user;
Future<void> fetchUserInfo(String userId) async {
_loading = true;
notifyListeners();
try {
final response = await ApiService.fetchUser(userId);
_user = UserModel.fromJson(response.data);
} catch (e) {
print(e);
} finally {
_loading = false;
notifyListeners();
}
}
}
这样通过 InheritedWidget(Provider 底层实现)传递状态,既保持了响应式的 UI 更新,又避免了过度复杂的架构。
踩坑经验:那些你不得不面对的问题
虽然整体开发体验不错,但在实践中我们也踩了不少坑,这里列出几个印象深刻的点:
1. iOS 打包签名失败:忘记配置 Info.plist
刚准备打包给测试同学时,iOS 报了一个错误:
"Missing info.plist key for photo access"
因为我们 App 用了相机上传头像功能,但 Info.plist 中未配置对应权限说明,导致审核失败。后来查文档发现需要添加如下内容:
<key>NSCameraUsageDescription</key>
<string>为了上传头像,请允许使用相机</string>
这类问题其实 RN 和 Flutter 都会出现,关键是要提前梳理所需权限,并做好构建脚本自动化处理。
2. Flutter 页面切换时黑屏或白屏
这个问题出现在 Android 上,尤其是低端机型或者系统版本较低的情况下。
解决方法是在 main.dart 中设置过渡模式:
void main() {
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
home: HomeScreen(),
theme: ThemeData.dark().copyWith(
pageTransitionsTheme: PageTransitionsTheme(
builders: {
TargetPlatform.android: OpenUpwardsPageTransitionsBuilder(),
TargetPlatform.iOS: CupertinoPageTransitionsBuilder(),
},
),
),
),
);
}
也可以自己封装透明渐入效果,提升用户体验。
3. 插件冲突与 Gradle 版本不一致
我们在集成第三方地图 SDK(高德)的时候,出现了严重的插件冲突:
Gradle version conflict between flutter and third-party plugin.
后来发现是某个地图插件使用的 Gradle 插件版本过低,手动修改 .android/build.gradle 中的 classpath 版本才解决。
这类问题是跨平台框架常见的痛点——很多插件更新慢,兼容性堪忧,尤其在国内环境下调试难度更大。
效果总结:一次投入,两倍回报
经过大约两个月的开发周期,我们完成了 TeamLink App 的上线版:
- Android/iOS 双平台共用约 85% 的代码
- 复杂 UI 和动效实现流畅,FPS 接近原生水平
- 构建时间控制在 5 分钟内,CI/CD 流程顺利跑通
- 一次提交即通过苹果审核(得益于提前处理了隐私政策等合规项)
更关键的是,在产品提出新的 UI 修改需求时,我们几乎不需要分别处理两端,效率提升了至少一倍以上。
经验分享:给正在做选择的你几点建议
如果你也在面临是否选择跨平台开发框架的抉择,结合我这几年的经验,分享几点建议:
✅ 如果你想快速验证 MVP 或者偏重交互的产品:
- 推荐 Flutter
- 控制力强,UI 表现一致,适合视觉敏感的场景
✅ 如果你的团队已有前端基础:
- 优先考虑 React Native
- 社区庞大,资源多,遇到问题更容易找到答案
❗ 如果你涉及大量原生功能调用或需要高度定制:
- 考虑混合开发(Hybrid),不要死磕全跨平台
- 有些地方还是得写一点 native 代码更稳妥
🚫 不要盲目追求“一套代码打天下”
- 实际中 100% 共享几乎不可能
- 很多时候还是得根据平台特性做一些差异化处理
⚠️ 别忽略应用市场的规范和限制
- 苹果审核严、Google Play 也有各种条条框框
- 隐私协议、权限申请流程、SDK 来源合法性都要注意
写在最后:关于跨平台开发的一些思考
坦白说,这两年跨平台技术发展迅猛,无论是 Flutter 还是 React Native,都已经从早期的“玩具框架”成长为可支撑大型 App 的生产级方案。
但作为一名一线开发者,我觉得我们更应该关注的是:解决问题本身,而不是沉迷于某种框架。
在我参与的多个项目中,真正决定成败的从来不是用了什么语言、什么技术栈,而是团队能否在有限时间内高效协同,能否准确理解业务需求,能否持续保障用户价值的交付。
至于 Flutter 和 React Native,它们都只是工具。而我们要做的,就是根据手头的任务选择最合适的那把锤子。
致读者
如果你正在犹豫要不要尝试跨平台开发,我希望这篇文章能给你一些参考。欢迎留言交流你们遇到的具体问题,我们一起讨论。
也欢迎点赞、收藏,让更多还在原生路上挣扎的同学看到这份实战笔记。
愿你在每一次技术选型中,都能少踩坑、多收获!

评论 0