3、Flutter Module创建:使用flutter create --template module创建模块、模块目录结构解析、与原生工程的依赖关系
好,咱们直接进入正题。这一章讲的是Flutter Module的创建,说白了就是怎么在原生项目里塞进一个Flutter模块。我刚开始搞混合开发时,也踩过不少坑,尤其是目录结构和依赖关系这块,容易让人懵。今天咱们一步步拆开来看。
3.1 使用flutter create --template module创建模块
创建Flutter Module,官方推荐用这条命令:
flutter create --template module my_flutter_module
这条命令会生成一个名为my_flutter_module的目录。它跟普通的Flutter项目不一样,不是用来独立运行的,而是作为原生工程的依赖库存在。
我个人习惯把模块名起得短一点,比如flutter_module,因为后面在原生工程里引用时,名字太长容易写错。嗯,这里要注意:模块名不要用驼峰,建议全小写加下划线,否则在Android的Gradle配置里可能会报错。
核心区别:普通Flutter项目有lib/main.dart作为入口,而Module项目没有main.dart,取而代之的是lib/main.dart(其实也有,但通常只放一个空壳)。真正的入口由原生工程通过FlutterEngine来启动。
3.2 模块目录结构解析
创建完成后,我们看看目录里都有什么。我直接列出来:
my_flutter_module/
├── .android/ # Android原生壳工程(隐藏,自动生成)
├── .ios/ # iOS原生壳工程(隐藏,自动生成)
├── lib/ # Dart代码目录
│ └── main.dart # 模块入口(通常只做导出)
├── test/ # 测试代码
├── pubspec.yaml # Flutter模块的依赖配置
├── build.gradle # Android构建配置(用于发布AAR)
└── CMakeLists.txt # 桌面端支持(可选)
这里有几个关键点,我当年第一次看到.android和.ios目录时,还以为是项目出错了。其实它们是Flutter自动生成的壳工程,用来在开发阶段调试用的。你想想看,如果没有这两个壳,你怎么在模拟器里跑Flutter代码?
但注意:这两个目录不要手动修改。每次执行flutter pub get或flutter build时,它们会被重新生成。我曾经手贱改过.android里的Gradle配置,结果下次构建时全被覆盖了,白忙活一场。
避坑指南:如果你需要自定义Android原生配置(比如修改minSdkVersion),应该在android/目录(如果有)或通过pubspec.yaml中的flutter:配置项来设置,而不是直接改.android。
3.3 与原生工程的依赖关系
这是最核心的部分。Flutter Module怎么跟原生工程关联起来?说白了就两种方式:
方式一:本地依赖(开发阶段)
在原生工程的settings.gradle里添加:
// Android
setBinding(new Binding([gradle: this]))
evaluate(new File(
settingsDir.parentFile,
'my_flutter_module/.android/include_flutter.groovy'
))
include ':my_flutter_module'
project(':my_flutter_module').projectDir = new File('../my_flutter_module')
然后在app/build.gradle里添加依赖:
implementation project(':flutter')
这种方式的好处是:你改Flutter代码后,热重载直接生效,不用重新打包。我平时开发都用这个方式,效率高。
方式二:AAR发布(生产阶段)
用命令打包成AAR:
flutter build aar
然后原生工程通过Maven仓库引用:
repositories {
maven {
url 'my_flutter_module/build/host/outputs/repo'
}
}
dependencies {
implementation 'com.example.flutter_module:flutter_release:1.0'
}
这种方式适合CI/CD流水线,或者给其他团队使用。但注意:每次Flutter代码更新,都需要重新打包AAR并更新版本号。
重要提醒:两种方式不要混用。如果你在开发阶段用了本地依赖,发布时又改成AAR,很容易出现版本不一致的问题。我建议:开发用本地依赖,发布前统一切到AAR并做一次完整回归测试。
3.4 依赖关系图
为了让你更直观地理解,我画了一张图:
这张图很清楚地展示了:原生工程不直接跟Flutter Module的Dart代码打交道,而是通过FlutterEngine这个中间层。所有的UI渲染、事件传递,都经过这个引擎。这也是为什么Flutter混合开发性能好的原因——它有自己的渲染引擎,不依赖原生控件。
3.5 实战建议
最后,我分享几个实战中的小经验:
- 模块位置:我建议把Flutter Module放在原生工程的同级目录,而不是子目录。这样两个项目各自独立,互不干扰。
- 版本管理:Flutter Module和原生工程最好在同一个Git仓库里,用submodule或者monorepo的方式管理。否则版本同步起来很痛苦。
- 依赖版本:Flutter Module的
pubspec.yaml里不要写死版本号,用^范围依赖。这样升级Flutter SDK时,依赖库能自动适配。
个人经验:我曾经在一个项目里,Flutter Module和原生工程分开两个Git仓库,结果每次发版都要手动确认版本对应关系,出了好几次线上事故。后来改成monorepo,用同一个pubspec.yaml管理版本,再也没出过问题。
好了,这一章的内容就到这里。创建Flutter Module其实不难,关键是理解它的目录结构和依赖关系。下一章我们会讲如何把Flutter Module集成到Android原生工程中,包括Gradle配置、FlutterEngine初始化等细节。
公众号:蓝海资料掘金营,微信deep3321