3、Android项目集成Flutter Module:在现有Android项目中通过Gradle配置引入Flutter Module,处理依赖冲突
好,咱们接着聊。上一章我们把Flutter Module搭起来了,但说实话,那只是个空壳子。真正的挑战在于——怎么把它塞进你那个已经跑了好几年的Android项目里。
我见过太多人卡在这一步。明明Flutter单跑没问题,Android单跑也没问题,一合起来就各种编译报错。嗯,这里要说的就是怎么优雅地解决这个问题。
3.1 两种集成方式,你选哪种?
Flutter官方给了两种集成方式,我分别说说我的看法。
| 方式 | 原理 | 适用场景 | 我个人的倾向 |
|---|---|---|---|
| AAR集成 | 把Flutter Module打包成AAR,放到Android项目里引用 | 团队分工明确,Flutter和Android开发分离 | 推荐,解耦更彻底 |
| 源码集成 | 直接在Android项目里引用Flutter Module的源码路径 | 小团队快速迭代,需要频繁改Flutter代码 | 初期可以用,但长期维护成本高 |
我个人习惯用AAR方式。为什么?你想想看,源码集成意味着你的Android项目要依赖Flutter的整个构建环境,包括Dart SDK、Flutter引擎等等。每次拉新同事入项目,光配环境就得折腾半天。我在项目中遇到过这种情况,后来果断切成了AAR,世界清净了。
3.2 源码集成:最直接的方案
如果你决定先用源码集成,那就在Android项目的settings.gradle里加上这么一段:
// 在 settings.gradle 中
// 假设你的Flutter Module路径是 ../flutter_module
setBinding(new Binding([gradle: this]))
evaluate(new File(
settingsDir.parentFile,
'flutter_module/.android/include_flutter.groovy'
))
include ':flutter_module'
project(':flutter_module').projectDir = new File('../flutter_module')
然后在app/build.gradle里添加依赖:
dependencies {
implementation project(':flutter_module')
// 其他依赖...
}
这样做的好处是,你改了Flutter代码,Android这边直接就能看到效果。但坏处也很明显——耦合太紧。我曾经有个项目,Flutter和Android的Gradle版本不一致,每次同步都要手动调,烦得很。
3.3 AAR集成:更专业的做法
这才是我想重点讲的。AAR集成的核心思路是:Flutter Module独立构建,输出AAR文件,Android项目只依赖这个产物。
首先,在Flutter Module里执行:
flutter build aar
这条命令会生成一个build/host/outputs/repo目录,里面就是AAR文件和对应的POM配置。然后你在Android项目的build.gradle里这样配:
// 项目级 build.gradle
allprojects {
repositories {
google()
mavenCentral()
// 添加Flutter的本地仓库
maven {
url '../flutter_module/build/host/outputs/repo'
}
}
}
// 模块级 build.gradle
dependencies {
// 注意:这里的版本号要和Flutter Module里的一致
implementation 'com.example.flutter_module:flutter_release:1.0.0'
}
这里有个坑,我踩过。Flutter生成的AAR版本号默认是1.0.0,但如果你改了Flutter Module的pubspec.yaml里的版本,它不会自动同步。所以每次构建AAR时,最好检查一下版本号。
核心要点:AAR集成方式下,Android项目完全不需要知道Flutter的存在。你只需要把生成的AAR文件放到公司的Maven私服上,其他同事直接引用就行。
3.4 依赖冲突:绕不开的坎
好,集成方式说完了。但真正让人头疼的是依赖冲突。Flutter自己带了一堆依赖,比如androidx.core、androidx.lifecycle等等。如果你的Android项目也用了这些库,版本不一致就会报错。
为什么会这样?说白了,Flutter引擎在编译时锁死了某些依赖的版本。你强行改版本,Flutter可能就跑不起来了。
我的处理策略是这样的:
- 先看冲突的是什么库。运行
./gradlew :app:dependencies,把依赖树打出来,找到冲突的库。 - 统一用Flutter的版本。除非你的Android项目有特殊要求,否则我建议跟着Flutter走。毕竟Flutter是外来户,动它的依赖风险更大。
- 使用force强制指定版本。在
build.gradle里加上:
configurations.all {
resolutionStrategy {
force 'androidx.core:core:1.9.0'
force 'androidx.lifecycle:lifecycle-common:2.5.1'
}
}
我曾经在一个项目里,因为androidx.appcompat版本冲突,折腾了两天。最后发现是Flutter的某个插件依赖了旧版本,而我的Android项目用了新版本。嗯,最后我选择了降级Android的版本,因为那个插件暂时没有更新计划。
警告:不要轻易使用exclude来排除Flutter的传递依赖。Flutter的运行时需要这些库,你排除了可能会导致Flutter页面加载失败或崩溃。
3.5 实战中的避坑指南
说了这么多理论,来点实际的。我总结了几条经验:
- 先跑通最小集。第一次集成时,不要带任何第三方Flutter插件。先让Flutter的Hello World跑起来,再加其他东西。
- 注意Gradle版本。Flutter 3.x要求Gradle 7.x以上,如果你的Android项目还在用Gradle 4.x,那得先升级。
- 小心Kotlin版本。Flutter的Android引擎是用Kotlin写的,如果你的项目用了Kotlin,版本最好和Flutter一致。我一般用1.8.x。
- 多模块项目要小心。如果你的Android项目有多个Module,确保每个Module都引用了Flutter的依赖,否则会出现ClassNotFoundException。
小技巧:在Android项目的gradle.properties里加上android.useAndroidX=true和android.enableJetifier=true。虽然现在新项目默认都开了,但老项目可能没开,这会导致Flutter的AndroidX依赖解析失败。
3.6 一张图看懂集成流程
说了这么多,我画了张图帮你理清思路:
这张图把整个流程串起来了。从Flutter Module开始,经过构建生成AAR,再到Android项目引用,最后处理依赖冲突。每一步都有坑,但按这个流程走,基本不会出大问题。
好了,这一章的内容就到这。记住,集成只是第一步,后面还有更多挑战等着我们。但只要你把依赖冲突这块啃下来,后面的路就好走多了。
公众号:蓝海资料掘金营,微信deep3321