Flutter 入门:从零开始构建跨平台应用的实战总结
开篇:为什么我要写这篇文章?

作为一个有五年开发经验的移动端工程师,我经历过原生 Android、iOS 的开发洗礼,也尝试过 React Native。但直到去年公司要做一个全新的项目,我第一次真正完整地用 Flutter 构建了一个跨平台应用之后,才算是彻底被这套框架“收买”。
在那之前,我对 Flutter 抱有一些偏见和误解,觉得它还是不够成熟、生态不如 React Native 丰富、性能也可能有问题……结果却是狠狠打了我的脸。
今天,我想以一个踩过坑、改过无数 Bug 的普通开发者身份,来分享一下我是如何从零开始构建一个 Flutter 应用,并且过程中经历了哪些真实的问题与解决方式。
问题描述:团队为何选择 Flutter?


这个项目背景很简单,是我们公司要上线一款面向全国用户的产品级 App,要求同时支持 iOS 和 Android 平台。团队规模不算大,前端和后端分开,但当时负责客户端的只有我和另一位同事。
我们做了调研后发现,如果采用传统的双平台原生开发方式,不仅人力成本高、开发周期长,而且在一些 UI 组件、交互逻辑上很难做到完全一致。
这时候,Flutter 走入我们的视野。它的最大吸引力在于:
- 一套代码跑两端(甚至未来可以扩展到 Web)
- 更统一的设计语言(基于 Skia 渲染引擎,UI 不依赖系统原生组件)
- 热重载功能极大提高了开发效率
但也存在很多未知的风险,比如:
- 是否有足够的社区资源支撑
- 插件是否能满足业务需求
- 性能和体验能否媲美原生
于是我们决定试一把,做一个原型先,看看这条路到底能不能走通。
解决方案:技术架构与选型思路

我们项目的初期目标是构建一个具备以下能力的基础框架:
- 支持主流路由跳转(Tab、Stack、BottomSheet 等)
- 实现网络请求封装、状态管理
- 支持本地存储(SharedPreferences / 文件读写)
- 集成第三方登录(微信、手机号验证码)
- 满足基本的 UI 设计规范(适配多设备屏幕)
最终我们确定了如下技术栈:
| 模块 | 技术选型 |
|---|---|
| 状态管理 | Bloc + Equatable |
| 网络请求 | Dio + InterceptorsWrapper |
| 数据存储 | shared_preferences + hive(部分数据) |
| 路由管理 | auto_route(配合 build_runner 自动生成) |
| UI 组件库 | 定制主题风格 + Material Design 3 |
| 第三方集成 | flutter_secure_storage, flutter_wechat_plugin |
整个项目采用分层设计模式,分为 presentation、domain、data 三层结构,类似于 Clean Architecture,虽然一开始大家学起来有点吃力,但从长期来看,这样的结构让维护变得容易不少。
代码实践:几个关键点的实现片段

1. 使用 Bloc 进行状态管理
Bloc 是我们团队非常喜欢的状态管理方案,因为它简单易懂,又足够灵活。
// 示例:登录 Bloc
class LoginBloc extends Bloc<LoginEvent, LoginState> {
final UserRepository _userRepository;
LoginBloc(this._userRepository) : super(LoginInitial());
@override
Stream<LoginState> mapEventToState(LoginEvent event) async* {
if (event is LoginButtonPressed) {
yield LoginLoading();
try {
final token = await _userRepository.login(event.username, event.password);
yield LoginSuccess(token: token);
} catch (e) {
yield LoginFailure(error: e.toString());
}
}
}
}

2. 自动化路由配置
我们采用了 auto_route 来管理页面跳转,减少手动写 Navigator.push 的繁琐。
# pubspec.yaml
auto_route:
generators:
auto_route_generator:
dependencies:
auto_route: ^4.0.1
然后使用注解的方式定义页面路由:
@RoutePage()
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('首页')),
body: Center(child: Text('欢迎来到首页')),
);
}
}
执行 flutter pub run build_runner watch 自动生成路由类,大大提升了开发效率。
3. 屏幕适配
Flutter 默认的像素单位是逻辑像素,所以我们需要做一次适配缩放处理。
// main.dart
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MediaQuery(
data: MediaQueryData.fromWindow(WidgetsBinding.instance.window)
.copyWith(textScaleFactor: 1.0),
child: MaterialApp.router(
routerConfig: router,
debugShowCheckedModeBanner: false,
),
);
}
}
我们还封装了一个 ScreenUtil 类用来适配字体大小、边距等:
// 像素换算工具
double dp(double val) {
var width = WidgetsBinding.instance.window.physicalSize.width;
var designWidth = 375; // iPhone 8 尺寸为参考
return val * width / designWidth;
}
踩坑经验:那些让我深夜失眠的问题
1. 微信支付接入遇到的问题
当时我们遇到了微信支付调起失败的问题,在 Android 上一切正常,但 iOS 上始终提示 "签名不正确"。
折腾了好几天才发现:
- 在 iOS 中,Flutter 编译后的 Bundle Identifier 必须与微信后台填写的一模一样。
- 由于调试包和发布包使用不同的 bundle identifier,导致签名验证一直失败。
解决方案是在 Xcode 的 Build Settings 中修改 product name,并确保与微信开放平台中的注册信息一致。
2. Android 10 及以上权限处理
Android 升级到 Q 以后,默认不再允许全局访问外部存储路径,这就给我们读取图片缓存、下载文件等操作带来了困难。
我们通过申请 Scoped Storage 权限并使用 path_provider 获取应用专属目录解决问题。
Directory appDocDir = await getApplicationDocumentsDirectory();
String path = appDocDir.path;
此外,还要在 AndroidManifest.xml 添加:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />
注意区分 API Level,因为 Android 10 及以上废弃了这些权限。
3. App Store 提交审核失败
最后发布阶段最头疼的是 App Store 的审核拒绝,原因居然是——“没有提供截图说明”。
我们在上传 IPA 包的时候,误以为只提交 Flutter 构建的 Release 包就可以,实际上 Apple Connect 后台还需要上传完整的应用截图,并填写隐私政策声明。
这提醒我们,发布前务必要提前准备好所有素材,包括图标、介绍文案、预览图,以及必要的合规文档。
效果总结:项目上线后的收获
经过两个月的开发和不断迭代,我们成功将 App 推向市场,iOS 和 Android 双平台都顺利通过审核,并且用户反馈良好。以下是几个关键成果:
- 代码复用率超过 80%,极大地节省了开发时间;
- 动画流畅性优于预期,特别是自定义的转场动画;
- 用户反馈中几乎没有出现明显的 Crash,说明稳定性不错;
- 通过插件和开源组件解决了大部分需求,社区支持力度强。
最关键的一点是:当我们想新增一个小功能时,只需要改一次代码,就能看到两个平台的效果。
经验分享:给刚入门 Flutter 的你几点建议
不要上来就追求复杂的状态管理
我自己最初就是太急着学习 BLoC、Riverpod,结果越学越晕。不妨先从setState开始,搞清楚生命周期和 widget 树的构建过程,再逐步引入状态管理机制。合理利用社区资源,避免重复造轮子
Flutter 社区非常活跃,很多时候你想到的功能早就有人实现了,直接搜 GitHub 或者 pub.dev,往往能找到合适的 package,节省大量时间。提前规划好路由结构和模块划分
路由混乱、页面跳转复杂是很多新手项目的通病。使用 auto_route、go_router 等工具,可以帮助你规范化页面导航逻辑。适配要趁早,后期修改代价大
手机型号越来越多,刘海屏、折叠屏、全面屏都得考虑到。建议尽早封装一个通用的 UI 工具类来应对不同设备尺寸。性能优化不是小事
比如过度渲染、冗余重建等问题,可以通过Widget Inspector查看构建耗时情况;使用const和ListView.builder等技巧减少不必要的 rebuild。持续学习 Dart 语言特性
Dart 不是 Java 或 JavaScript,有些语法习惯可能不一样,特别是异步编程、Stream、泛型这些地方,掌握好才能写出更优雅的 Flutter 代码。
结语:Flutter 让我重新爱上了移动开发
说实话,写这篇文章的时候,我已经用 Flutter 做完第三个项目了,从最初的抗拒到现在离不开它,这是一个很奇妙的过程。
也许现在还有不少人对 Flutter 存疑,但它确实在一步步走向成熟。我相信,未来 Flutter 会在更多场景中替代传统开发方式,成为主流的跨平台方案。
如果你正在考虑入手 Flutter,不妨试试。哪怕只是做个 Demo,也能体会到那种“写一次,跑两边”的快感。
毕竟,代码写得好不好无所谓,关键是开心啊 🤣。
如果你也正在用 Flutter 或者刚入坑,欢迎留言交流,一起探讨踩过的那些坑!

评论 0