01 概览与环境搭建
1.1 Flutter 是什么
Flutter 是 Google 开源的跨平台 UI 框架。一套 Dart 代码,可以编译成 Android、iOS、Web、Windows、macOS、Linux 应用;社区分支 Flutter OH 还支持 OpenHarmony / HarmonyOS NEXT(鸿蒙)。
它的核心特点是“自绘”:
- 不把 Dart 组件翻译成原生控件(React Native 是这么做的),而是由 Flutter Engine 直接通过 GPU(Vulkan / Metal / OpenGL ES)把每一个像素画到平台提供的一块 Surface 上。
- 因此各平台 UI 像素级一致,不受系统控件版本影响;代价是包里要带一个渲染引擎(Android 上约 +4~6MB),并且要和原生控件混排时需要额外机制(PlatformView)。
1.2 与其他方案对比
| 维度 | Android 原生 (View/Compose) | Flutter | React Native | KMP + Compose Multiplatform |
|---|---|---|---|---|
| 语言 | Kotlin/Java | Dart | JS/TS | Kotlin |
| UI 渲染 | 系统 View / Compose(Skia/HWUI) | 自绘(Impeller/Skia) | 原生控件(Fabric) | 自绘(Skia),Android 端用原生 Compose |
| 跨端一致性 | — | 极高 | 中(控件随平台) | 高 |
| 性能 | 最好 | 接近原生,AOT 编译 | 比 Flutter 弱,JSI 后改善 | 接近原生 |
| 鸿蒙支持 | 无 | 社区 Flutter OH,较成熟 | 社区 RNOH | 社区在做,较早期 |
| 生态 | 最大 | pub.dev,较大 | npm,大 | 较小,快速增长 |
| 动态化 | 插件化/热修 | 官方不支持代码下发(AOT),可用 Shorebird 等 | 支持 bundle 下发 | 不支持 |
选择建议:业务以 UI 为主、需要三端(含鸿蒙)一致、团队愿意学 Dart,选 Flutter;强依赖动态下发选 RN;只想复用逻辑层选 KMP。
1.3 心智模型对照(Android → Flutter)
| Android | Flutter | 说明 |
|---|---|---|
| Activity / Fragment | Route / Page(一个 Widget) | Flutter 默认只有一个 FlutterActivity,页面切换在 Flutter 内部完成 |
| View / ViewGroup | Widget | Widget 是不可变的配置描述,不是真正的视图对象 |
| XML 布局 | Dart 代码嵌套 Widget | 没有 XML,类似 Compose |
findViewById + 改属性 |
改 state,调用 setState 重建 |
声明式 |
| RecyclerView + Adapter | ListView.builder |
自带懒加载与回收 |
| LinearLayout | Row / Column |
|
| FrameLayout | Stack |
|
| ConstraintLayout | 无直接对应,组合 Row/Column/Stack/Expanded/Align |
|
res/drawable、res/values |
assets/ + pubspec.yaml 声明 |
|
| Gradle 依赖 | pubspec.yaml 依赖,来源 pub.dev |
|
| Intent / startActivity | Navigator.push / context.go() |
|
| Handler / Looper / 协程 | Future、async/await、Stream、Isolate |
Dart 单线程事件循环 |
| ViewModel + LiveData/Flow | ChangeNotifier / Riverpod / Bloc + Stream | |
| SharedPreferences | shared_preferences 插件 |
底层就是调 Android 的 SharedPreferences |
| Room | sqflite / drift |
|
| Retrofit + OkHttp | dio / http + retrofit(dart) |
|
| Glide | Image.network + cached_network_image |
|
| JNI | dart:ffi |
直接调 C,比 JNI 简单 |
onCreate/onResume |
initState / AppLifecycleListener |
1.4 环境搭建(macOS 为例)
1.4.1 安装 Flutter SDK
推荐用 FVM 管理多版本(官方 Flutter 和鸿蒙 Flutter OH 需要并存):
# 方式一:直接 git clone(简单)
git clone https://github.com/flutter/flutter.git -b stable ~/sdk/flutter
echo 'export PATH="$HOME/sdk/flutter/bin:$PATH"' >> ~/.zshrc
# 国内镜像(官方提供),网络慢时设置
echo 'export PUB_HOSTED_URL=https://pub.flutter-io.cn' >> ~/.zshrc
echo 'export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn' >> ~/.zshrc
source ~/.zshrc
# 方式二:FVM(推荐团队使用,项目内锁定版本)
brew tap leoafarias/fvm && brew install fvm
fvm install stable
cd your_project && fvm use stable # 生成 .fvmrc,项目锁版本
1.4.2 检查环境
flutter doctor -v
逐项解决 doctor 的报错:
- Android toolchain:使用已有的 Android SDK。若提示 license,执行
flutter doctor --android-licenses。需要 JDK 17+(Flutter 3.47 最低要求 Java 17)。 - Xcode(仅 macOS,做 iOS 需要):App Store 安装 Xcode,然后
sudo xcode-select -s /Applications/Xcode.app && sudo xcodebuild -runFirstLaunch。Flutter 3.44 起 iOS 默认用 Swift Package Manager,不再强制安装 CocoaPods。 - IDE:Android Studio 安装 Flutter 插件(会自动装 Dart 插件);或 VS Code 安装 Flutter 扩展。
1.4.3 创建并运行第一个工程
flutter create --org com.example --platforms android,ios flutter_playground
cd flutter_playground
flutter devices # 列出设备(真机/模拟器)
flutter run # 默认 debug 模式,支持热重载
运行后在终端按:
r:Hot Reload(热重载,保留状态,约 1 秒内生效)R:Hot Restart(重启 Dart 层,状态丢失,不重装 APK)q:退出
Android Studio 中点工具栏的闪电图标就是 Hot Reload。
1.5 工程结构
flutter_playground/
├── pubspec.yaml # ≈ build.gradle:依赖、资源、版本号
├── pubspec.lock # 依赖锁定(应用工程要提交到 git)
├── analysis_options.yaml # lint 规则 ≈ lint.xml / detekt
├── lib/ # Dart 源码,入口 lib/main.dart
├── test/ # 单元测试 / Widget 测试
├── assets/ # 自建,图片/字体/json 等资源
├── android/ # 一个标准 Android Gradle 工程(宿主壳)
│ └── app/src/main/kotlin/.../MainActivity.kt # 继承 FlutterActivity
├── ios/ # Xcode 工程(宿主壳)
└── ohos/ # 鸿蒙宿主工程(使用 Flutter OH 时才有)
android/ 目录你会非常熟悉:它就是普通 Gradle 工程,Flutter 通过 dev.flutter.flutter-gradle-plugin 在构建时把 Dart 代码编译产物(libapp.so)和引擎(libflutter.so)打进 APK。
pubspec.yaml 示例
name: flutter_playground
description: Demo
publish_to: 'none' # 应用不发布到 pub.dev
version: 1.0.0+1 # versionName+versionCode
environment:
sdk: ^3.9.0
dependencies:
flutter:
sdk: flutter
dio: ^5.7.0 # 版本约束:^5.7.0 表示 >=5.7.0 <6.0.0
go_router: ^16.0.0
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^6.0.0
flutter:
uses-material-design: true
assets:
- assets/images/
fonts:
- family: MyFont
fonts:
- asset: assets/fonts/MyFont-Regular.ttf
上面依赖的版本号仅作示意,实际以 flutter pub add dio 生成的为准。
常用命令:
flutter pub add dio # 添加依赖(自动写入 pubspec)
flutter pub get # ≈ Gradle sync
flutter pub upgrade --major-versions
flutter pub outdated # 查看可升级依赖
flutter clean # 清理构建缓存
flutter analyze # 静态检查
flutter test # 跑测试
flutter build apk --release # 出包;还有 appbundle / ipa / hap
1.6 第一个程序解读
import 'package:flutter/material.dart';
// 入口,等价于 Application + 启动 Activity
void main() {
runApp(const MyApp());
}
// 无状态组件:只依赖构造参数
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp( // 提供主题、路由、本地化等
title: 'Demo',
theme: ThemeData(colorSchemeSeed: Colors.blue),
home: const CounterPage(),
);
}
}
// 有状态组件:Widget 本身不可变,可变状态放在 State 里
class CounterPage extends StatefulWidget {
const CounterPage({super.key});
@override
State<CounterPage> createState() => _CounterPageState();
}
class _CounterPageState extends State<CounterPage> {
int _count = 0; // 下划线开头 = 库私有
@override
Widget build(BuildContext context) {
return Scaffold( // ≈ 带 Toolbar/FAB 的页面骨架
appBar: AppBar(title: const Text('计数器')),
body: Center(child: Text('点击了 $_count 次')),
floatingActionButton: FloatingActionButton(
onPressed: () => setState(() => _count++), // 标记脏 → 下一帧重建
child: const Icon(Icons.add),
),
);
}
}
关键点:
setState不是“立刻刷新”,而是把当前 Element 标记为 dirty,下一帧(VSync 到来时)重新调用build。build会被频繁调用(每帧都可能),所以里面不能做耗时操作,也不要在里面创建 Controller、发网络请求。const构造的 Widget 在编译期创建,重建时被跳过,是最基础的性能优化。
动手练习
- 安装环境,
flutter doctor全绿(iOS 项可选)。 - 创建工程,在真机运行计数器,修改文字颜色后按
r体验热重载,再按R观察计数被清零。 - 打开
android/app/build.gradle(.kts)和MainActivity.kt,找到applicationId、minSdk,对照你熟悉的 Android 工程。 - 执行
flutter build apk --release --split-per-abi,用 Android Studio 的 APK Analyzer 打开产物,找到libflutter.so、libapp.so、flutter_assets/。