3、Flutter Module创建:在现有Android项目中集成Flutter Module、目录结构解析
好,咱们直接进入正题。上一章我们把Flutter环境搭好了,也跑通了第一个Demo。但说实话,那都是「玩具项目」。真正的战场,是在一个已经跑了好几年的Android原生项目里,把Flutter塞进去。
嗯,这里要注意。我说的「塞进去」不是简单的加个依赖完事。而是要让Flutter和Android和平共处,互不干扰。我见过太多团队,集成完Flutter之后,Android编译时间从3分钟变成15分钟,打包体积直接翻倍。说白了,就是姿势不对。
3.1 两种集成方式:Module vs 源码依赖
先搞清楚概念。Flutter官方给了两种集成方式:
| 方式 | 原理 | 适用场景 |
|---|---|---|
| Flutter Module | 以AAR/APK形式输出,Android通过Maven依赖 | 团队协作、CI/CD、解耦 |
| 源码依赖 | 直接把Flutter工程作为Android的子模块 | 快速原型、个人项目 |
我个人习惯用Flutter Module方式。为什么?因为源码依赖会让你的Android项目变得非常「重」。你想想看,每次编译都要把Flutter引擎、Dart代码、原生插件全部重新编译一遍。我曾在项目里试过,一次clean build要等20分钟。后来切到Module方式,编译时间直接降到5分钟以内。
3.2 创建Flutter Module
假设你的Android项目在 /Users/me/workspace/MyAndroidApp 目录下。我们就在这个目录的同级,创建一个Flutter Module。
cd /Users/me/workspace
flutter create --template module my_flutter_module
这条命令会生成一个 my_flutter_module 目录。注意参数 --template module,它告诉Flutter:我要的不是一个独立App,而是一个可以被Android/iOS引用的模块。
my_flutter_module。不要用驼峰,否则在Android的Gradle配置里容易出问题。我踩过这个坑。
3.3 目录结构解析
创建完之后,我们看看这个Module长什么样。用 tree -L 2 看一下:
my_flutter_module/
├── .android/ # Android壳工程(用于调试)
├── .ios/ # iOS壳工程(用于调试)
├── lib/ # Dart代码目录
│ └── main.dart # 入口文件
├── test/ # 测试代码
├── .metadata # Flutter内部元数据
├── .packages # 包依赖映射
├── pubspec.yaml # 依赖配置文件
└── README.md # 说明文档
我来逐个解释这些目录的作用:
- .android/ — 这是一个完整的Android工程。但它不是给你直接用的,而是给Flutter调试用的。当你用
flutter run启动Module时,Flutter会编译这个壳工程。注意,这个目录是自动生成的,不要手动修改。 - .ios/ — 同理,iOS的壳工程。
- lib/ — 你的Dart代码都放这里。注意,Module的入口文件是
main.dart,但它和独立App的main.dart不一样。Module的main.dart通常只做初始化,不启动UI。 - pubspec.yaml — 这是Flutter的「Gradle文件」。所有第三方库、插件、资源都在这里声明。
.android/ 目录提交到Git仓库。它每次 flutter pub get 或 flutter build 都可能被重新生成。正确的做法是在 .gitignore 里忽略它。
3.4 核心文件:pubspec.yaml 详解
我们打开 pubspec.yaml,看看里面有什么:
name: my_flutter_module
description: A new Flutter module.
version: 1.0.0+1
environment:
sdk: ">=2.17.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
# 这里加你的第三方依赖
# http: ^0.13.0
# provider: ^6.0.0
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
uses-material-design: true
# 这里声明资源文件
# assets:
# - images/
# - fonts/
这里有几个关键点:
- name — 模块名,必须和目录名一致。否则Gradle集成时会找不到。
- environment.sdk — 指定Dart SDK版本范围。建议用
>=2.17.0 <3.0.0,兼容性最好。 - dependencies — 这里只声明Flutter SDK依赖。其他第三方库按需添加。
provider(状态管理)和 dio(网络请求),其他能省则省。
3.5 集成到Android项目
现在,我们要把Flutter Module集成到Android项目里。这一步是核心,也是容易出错的地方。
首先,在Android项目的 settings.gradle 里添加:
// 在文件末尾添加
setBinding(new Binding([gradle: this]))
evaluate(new File(
settingsDir.parentFile,
'my_flutter_module/.android/include_flutter.groovy'
))
然后,在 app/build.gradle 里添加依赖:
dependencies {
implementation project(':flutter')
// 其他依赖...
}
嗯,这里要注意。很多新手会问:为什么是 project(':flutter')?因为 include_flutter.groovy 脚本会自动创建一个名为 flutter 的Gradle子模块。这个子模块指向的就是你的Flutter Module。
Could not find method setBinding()。后来发现是 settings.gradle 的写法不对。正确的做法是:setBinding 必须在 include ':app' 之后调用,否则Gradle找不到项目。
3.6 知识体系图
下面我用一张SVG图,把整个集成流程串起来。你看完应该就清楚了:
3.7 验证集成是否成功
集成完之后,怎么验证?我一般做三步检查:
- 编译检查 — 在Android项目根目录执行
./gradlew assembleDebug,看能否编译通过。 - 运行检查 — 在Android Studio里直接运行App,看Flutter页面能否正常显示。
- 热重载检查 — 修改Flutter代码,看Android端能否实时更新。如果能,说明集成成功。
Flutter engine not found,多半是Flutter SDK路径没配置对。检查一下 local.properties 里的 flutter.sdk 路径是否正确。
好了,这一章的内容就到这里。你跟着做一遍,应该就能把Flutter Module集成到Android项目里了。下一章我们会讲如何在Android代码里启动Flutter页面,以及如何传递数据。
公众号:蓝海资料掘金营,微信deep3321