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.coreandroidx.lifecycle等等。如果你的Android项目也用了这些库,版本不一致就会报错。

为什么会这样?说白了,Flutter引擎在编译时锁死了某些依赖的版本。你强行改版本,Flutter可能就跑不起来了。

我的处理策略是这样的:

  1. 先看冲突的是什么库。运行./gradlew :app:dependencies,把依赖树打出来,找到冲突的库。
  2. 统一用Flutter的版本。除非你的Android项目有特殊要求,否则我建议跟着Flutter走。毕竟Flutter是外来户,动它的依赖风险更大。
  3. 使用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=trueandroid.enableJetifier=true。虽然现在新项目默认都开了,但老项目可能没开,这会导致Flutter的AndroidX依赖解析失败。

3.6 一张图看懂集成流程

说了这么多,我画了张图帮你理清思路:

Flutter Module 集成 Android 项目流程 Flutter Module flutter build aar AAR 产物 maven 仓库 Android 项目 依赖冲突处理:force / 统一版本 最终APK:Android + Flutter 混合运行 两种方式:源码集成(左) vs AAR集成(右),推荐AAR方式

这张图把整个流程串起来了。从Flutter Module开始,经过构建生成AAR,再到Android项目引用,最后处理依赖冲突。每一步都有坑,但按这个流程走,基本不会出大问题。

好了,这一章的内容就到这。记住,集成只是第一步,后面还有更多挑战等着我们。但只要你把依赖冲突这块啃下来,后面的路就好走多了。


公众号:蓝海资料掘金营,微信deep3321