Flutter入门:从零开始构建跨平台应用
上周五晚上十一点,我坐在上海出租屋的书桌前,咖啡已经凉了三轮,窗外陆家嘴的霓虹灯还亮着。突然收到产品经理的消息:“老板说下周demo要给投资人看,iOS和Android版本都得有。” 我心想:这不就是典型的“临时加需求”剧本吗?但转念一想——正好!最近不是在研究Rust吗?等等不对……我是想试试 Flutter!
作为一名常年在各种 AI 编程工具之间反复横跳的评测博主(对,就是那个经常半夜发推吐槽 Copilot 的人),我对“一次编写、多端运行”这种口号早就免疫了。React Native 踩过坑,uni-app 也用过,Electron 更是让我对“跨平台”三个字产生了 PTSD。但这次,我决定给 Flutter 一个机会。
为啥选 Flutter?不是被逼的,是真的香
其实早在去年双11期间,我就偷偷试过 Flutter。当时公司要做一个内部运维小工具,要求快速上线 iOS 和 Android。前端团队人手不够,后端又不想碰 WebView,最后我这个“全栈边缘人”被推了出来。
一开始我是拒绝的:“又要学新框架?我 Rust 还没搞明白呢!” 但看了几个 demo 视频,发现 Flutter 的 UI 渲染完全自绘(Skia 引擎),不像 RN 那样依赖原生组件,理论上性能更稳、UI 更统一。而且 Dart 语言……嗯,虽然有点像 Java 和 JavaScript 的私生子,但上手意外地快。
最关键的是——热重载(Hot Reload)真的救我狗命。改一行代码,App 瞬间刷新,状态还不丢。比起以前改个样式等 Webpack 打包两分钟,现在简直是飞升体验。
从 flutter create 到第一个页面:别被文档吓到
安装 Flutter SDK 其实挺简单,官方文档写得也算清晰(比某些国产框架强一百倍)。我在 M1 Mac 上直接 brew install --cask flutter,然后跑了个 flutter doctor,结果报了一堆红:
[✗] Xcode - develop for iOS apps
✗ Xcode installation is incomplete.
[!] Android toolchain - develop for Android devices
✗ Unable to locate Android SDK.
行吧,老程序员了,见怪不怪。装完 Xcode Command Line Tools 和 Android Studio 后,终于看到满屏绿色 ✅。那一刻,我差点感动哭了——这可能是今年最顺利的一次环境配置。
接着,一行命令创建项目:
flutter create my_first_flutter_app
cd my_first_flutter_app
flutter run
模拟器弹出来,经典的 “Hello World” 页面。但别急着删它!这个默认模板其实是个很好的起点,包含了 AppBar、Scaffold、Text 等基础组件的用法。
我做的第一件事,就是把 main.dart 里的内容替换成一个简单的任务列表。目标很明确:首页显示待办事项,点击可标记完成,底部有个“+”按钮添加新任务。
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Todo',
theme: ThemeData(primarySwatch: Colors.blue),
home: TodoListScreen(),
);
}
}
Dart 的语法有点啰嗦(比如每个类都要显式继承),但 IDE(我用 VS Code + Flutter 插件)能自动补全,所以实际写起来并不痛苦。而且 Widget build 这种函数式 UI 构建方式,一旦习惯,反而觉得比 JSX 更“声明式”。
踩坑实录:你以为的跨平台,其实是“跨坑”
理想很丰满,现实很骨感。当我把 App 跑在 iOS 模拟器和 Android 真机上时,问题来了:
- 状态栏颜色不一致:iOS 默认是黑字,Android 是白字,导致在深色背景上看不见。
- 字体渲染差异:同样的
TextStyle(fontSize: 16),在 iPhone 上显得更细。 - 返回手势行为不同:Android 有物理返回键,iOS 是侧滑返回,逻辑处理要分开。
这时候我才意识到:Flutter 虽然号称“一套代码跑两端”,但你仍然需要关心平台特性。不过好在官方提供了 Platform.isIOS 这种判断,也能用 ThemeData 统一视觉规范。
更头疼的是本地存储。我一开始图省事,直接用 shared_preferences 存 JSON 字符串。结果测试同事反馈:“切换账号后数据没清!” 原来 shared_preferences 是全局持久化的,不适合用户上下文数据。
后来改用 hive(一个轻量级 NoSQL 数据库),配合 Provider 做状态管理,才搞定。不过说实话,Flutter 的生态库质量参差不齐,有些 package 最后更新还是 2020 年……选型时得瞪大眼睛看 GitHub Stars 和 issue 活跃度。
性能优化:别让“丝滑”变成“卡顿”
作为评测博主,我特别在意性能指标。用 Flutter DevTools 测了一下,初始版本帧率只有 45 FPS,尤其是在列表滚动时掉帧明显。
问题出在哪儿?原来我每个任务项都用了 Container 嵌套三层,还加了阴影和圆角。更致命的是——没用 const 构造函数!
Dart 里如果 Widget 是 const 的,重建时会直接复用,避免不必要的 rebuild。改完之后:
class TodoItem extends StatelessWidget {
final String title;
final bool completed;
const TodoItem({Key? key, required this.title, required this.completed}) : super(key: key);
@override
Widget build(BuildContext context) {
return const ListTile( // 注意这里的 const
title: Text('...'),
);
}
}
帧率立马回到 60 FPS。另外,长列表一定要用 ListView.builder 而不是直接 map 生成所有 item,否则内存爆炸分分钟教你做人。
发布上线:Google Play 审核比想象中宽松
开发完功能,下一步就是打包发布。Flutter 的构建命令很直观:
flutter build apk --release # Android
flutter build ios --release # iOS(需在 Mac 上)
但 iOS 打包真是劝退流程:需要 Apple Developer 账号、证书、Provisioning Profile……我在 Xcode 里折腾了两个小时,最后靠 flutter build ipa 一键生成 .ipa 文件才解脱。
上传 Google Play 时,审核只用了 2 小时(比我司测试流程还快!)。而 App Store……等了三天,理由是“你的 App 没有隐私政策链接”。行吧,赶紧用免费模板生成一个,重新提交。
有趣的是,APK 体积比预期大。默认 release 包有 15MB 左右,因为 Flutter 引擎要打包进去。不过开启 R8 混淆和 split per ABI 后,能压到 8MB 以内。对于一个跨平台应用来说,勉强能接受。
综合对比:Flutter vs 其他方案
为了写这篇教程,我还横向对比了几种主流跨平台方案:
| 方案 | 开发效率 | 性能 | UI 一致性 | 学习成本 | 社区生态 |
|---|---|---|---|---|---|
| Flutter | ⭐⭐⭐⭐☆ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐☆ | ⭐⭐⭐⭐ |
| React Native | ⭐⭐⭐⭐⭐ | ⭐⭐⭐☆ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| uni-app | ⭐⭐⭐⭐ | ⭐⭐☆ | ⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ |
| 原生开发 | ⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
结论很清晰:如果你追求极致性能和 UI 一致性,且团队能接受学习 Dart,Flutter 是目前最靠谱的跨平台选择。尤其适合 MVP 快速验证、内部工具、或对动画/自定义 UI 要求高的场景。
写在最后:凌晨三点的成就感
昨天凌晨三点,我把最终版 App 交给产品经理。他回了个 😳 表情,说“投资人很喜欢,问能不能加个暗黑模式”。
我笑了笑,没说话。因为我知道,在 Flutter 里,加暗黑模式只需要:
theme: ThemeData.light(),
darkTheme: ThemeData.dark(),
再配合 MediaQuery.of(context).platformBrightness 判断系统主题,半小时搞定。
这就是技术的魅力——当你掌握了一个趁手的工具,那些曾经让你熬夜掉头发的需求,突然就变得 trivial 了。
当然,Flutter 不是银弹。复杂业务逻辑、大量原生交互(比如蓝牙、NFC)、或者需要深度集成第三方 SDK 的场景,可能还是得回归原生。但对我这种既要写 Rust 又要应付 PM 的“杂工型”开发者来说,Flutter 真的是一剂良药。
如果你也在被“双端需求”折磨,不妨今晚就 flutter create 一下。说不定,明天你也能在凌晨三点,喝着冰美式,看着满屏绿的 flutter run 输出,露出老父亲般的微笑。
P.S. 下期我打算写《用 Rust 写 Flutter 插件:性能榨干指南》,感兴趣的话评论区吼一声~

评论 0