Flutter 入门:从零开始构建跨平台应用的实战总结

接口余额不足
2025-06-25 04:00
阅读 438

开篇:为什么我要写这篇文章?

开篇:为什么我要写这篇文章?

作为一个有五年开发经验的移动端工程师,我经历过原生 Android、iOS 的开发洗礼,也尝试过 React Native。但直到去年公司要做一个全新的项目,我第一次真正完整地用 Flutter 构建了一个跨平台应用之后,才算是彻底被这套框架“收买”。

在那之前,我对 Flutter 抱有一些偏见和误解,觉得它还是不够成熟、生态不如 React Native 丰富、性能也可能有问题……结果却是狠狠打了我的脸。

今天,我想以一个踩过坑、改过无数 Bug 的普通开发者身份,来分享一下我是如何从零开始构建一个 Flutter 应用,并且过程中经历了哪些真实的问题与解决方式。


问题描述:团队为何选择 Flutter?

应用性能监控-1

问题描述:团队为何选择 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

整个项目采用分层设计模式,分为 presentationdomaindata 三层结构,类似于 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

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 的你几点建议

  1. 不要上来就追求复杂的状态管理
    我自己最初就是太急着学习 BLoC、Riverpod,结果越学越晕。不妨先从 setState 开始,搞清楚生命周期和 widget 树的构建过程,再逐步引入状态管理机制。

  2. 合理利用社区资源,避免重复造轮子
    Flutter 社区非常活跃,很多时候你想到的功能早就有人实现了,直接搜 GitHub 或者 pub.dev,往往能找到合适的 package,节省大量时间。

  3. 提前规划好路由结构和模块划分
    路由混乱、页面跳转复杂是很多新手项目的通病。使用 auto_route、go_router 等工具,可以帮助你规范化页面导航逻辑。

  4. 适配要趁早,后期修改代价大
    手机型号越来越多,刘海屏、折叠屏、全面屏都得考虑到。建议尽早封装一个通用的 UI 工具类来应对不同设备尺寸。

  5. 性能优化不是小事
    比如过度渲染、冗余重建等问题,可以通过 Widget Inspector 查看构建耗时情况;使用 constListView.builder 等技巧减少不必要的 rebuild。

  6. 持续学习 Dart 语言特性
    Dart 不是 Java 或 JavaScript,有些语法习惯可能不一样,特别是异步编程、Stream、泛型这些地方,掌握好才能写出更优雅的 Flutter 代码。


结语:Flutter 让我重新爱上了移动开发

说实话,写这篇文章的时候,我已经用 Flutter 做完第三个项目了,从最初的抗拒到现在离不开它,这是一个很奇妙的过程。

也许现在还有不少人对 Flutter 存疑,但它确实在一步步走向成熟。我相信,未来 Flutter 会在更多场景中替代传统开发方式,成为主流的跨平台方案。

如果你正在考虑入手 Flutter,不妨试试。哪怕只是做个 Demo,也能体会到那种“写一次,跑两边”的快感。

毕竟,代码写得好不好无所谓,关键是开心啊 🤣。


如果你也正在用 Flutter 或者刚入坑,欢迎留言交流,一起探讨踩过的那些坑!

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝