4、Android原生项目集成Flutter Module(方式一:源码依赖)

好,咱们直接进入正题。源码依赖这种方式,说白了就是把 Flutter 模块当作一个 Android Library 来用。我刚开始接触这个方案时,也觉得挺绕的——明明是两个不同的技术栈,怎么就能揉到一起?但实际跑通之后你会发现,这其实是 Flutter 官方最推荐的方式,调试起来最方便,代码改动也能实时生效。

4.1 准备工作:项目结构长什么样?

先说说项目结构。我个人习惯把 Flutter Module 放在 Android 项目的同级目录下,而不是塞进 Android 项目里面。这样两个项目各自独立,互不干扰。

MyProject/
├── android/          # 原生 Android 项目
├── flutter_module/   # Flutter Module(新建的)
└── settings.gradle   # 关键文件,稍后要改

嗯,这里要注意:Flutter Module 不是用 flutter create 创建的普通项目,而是用 flutter create --template module 创建的。我见过不少新手直接拿普通 Flutter 项目往里塞,结果编译报错一脸懵。

创建命令:
flutter create --template module flutter_module

执行完后,你会看到 flutter_module 目录下多了一个 .android 文件夹,这就是 Flutter 自动生成的 Gradle 工程。

4.2 settings.gradle 配置:把 Flutter Module 引进来

这是整个集成过程中最关键的一步。settings.gradle 就像 Android 项目的「通讯录」,你得告诉它 Flutter Module 住在哪。

打开 Android 项目根目录下的 settings.gradle,加入以下代码:

// 在文件最前面添加
setBinding(new Binding([gradle: this]))
evaluate(new File(
    settingsDir.parentFile,
    'flutter_module/.android/include_flutter.groovy'
))

// 如果你想把 Flutter Module 也作为一个模块引入(可选)
include ':flutter_module'
project(':flutter_module').projectDir = new File('../flutter_module')

这里我解释一下 setBindingevaluate 的作用。说白了,Flutter 的 Gradle 脚本需要知道 Android 项目的「上下文」,才能正确生成对应的配置。我刚开始做的时候,漏掉了 setBinding 这一行,结果编译时一直报 flutter_embedding 找不到,折腾了半小时才发现是这个问题。

注意:路径中的 settingsDir.parentFile 是相对于 settings.gradle 文件所在目录的上一级。如果你的 Flutter Module 放在别的位置,记得调整路径。

4.3 app/build.gradle 配置:添加依赖

settings.gradle 配置好之后,接下来就是告诉 app 模块:「嘿,你要用 Flutter 的东西了」。

打开 app/build.gradle,在 dependencies 块中添加:

dependencies {
    implementation project(':flutter')
    // 其他依赖...
}

等等,这里有个坑。你可能会想,为什么是 :flutter 而不是 :flutter_module?这是因为 Flutter 的 Gradle 脚本在 include_flutter.groovy 中已经帮你注册了一个名为 :flutter 的模块。我一开始也写成了 :flutter_module,结果 Gradle 报错说找不到这个模块。

另外,如果你的项目用了 Java 8 或更高版本,还需要在 android 块中配置 Java 编译选项:

android {
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

为什么要配这个?因为 Flutter 的引擎库用到了 Java 8 的一些特性。我记得有一次升级 Flutter 版本后,编译突然报 lambda expressions 相关的错误,排查了半天才发现是 Java 版本没对齐。

4.4 同步与构建:跑起来看看

配置完成后,点击 Android Studio 的「Sync Now」按钮。如果一切顺利,你会看到 Gradle 开始下载 Flutter 相关的依赖,包括 flutter_embeddingsky_engine 等。

同步成功后,就可以在 Java/Kotlin 代码中使用 Flutter 了。比如在 MainActivity 中启动一个 Flutter 页面:

// Java 示例
findViewById(R.id.button).setOnClickListener(view -> {
    startActivity(
        FlutterActivity.createDefaultIntent(this)
    );
});

构建时,我建议先用 ./gradlew assembleDebug 命令来验证,而不是直接点运行按钮。因为命令行会输出更详细的日志,方便排查问题。

4.5 常见错误排查:我踩过的那些坑

这部分我重点说说,因为源码依赖这种方式,坑确实不少。我把常见的错误分成了几类:

错误现象 可能原因 解决方案
找不到 :flutter 模块 settings.gradle 中路径配置错误 检查 evaluate 中的路径是否正确指向 include_flutter.groovy
编译报 flutter_embedding 相关错误 Flutter SDK 版本与 Gradle 插件版本不兼容 运行 flutter doctor 检查环境,或升级 Flutter SDK
运行时崩溃:FlutterEngine not found Flutter 引擎库未正确打包 检查 app/build.gradle 中是否添加了 implementation project(':flutter')
Gradle 同步超慢 Flutter 依赖下载缓慢(尤其是第一次) 配置国内镜像源,或使用 --offline 模式

我曾经遇到过一个特别诡异的问题:编译成功了,但运行后 Flutter 页面一片空白。查了半天,发现是 Flutter Module 中的 pubspec.yaml 里声明了某个插件,但 Android 项目没有对应的依赖。所以,如果你用了 Flutter 插件,记得在 app/build.gradle 中也加上对应的 Android 依赖。

小技巧:如果遇到编译错误,先试试 flutter clean./gradlew clean 双清。很多时候,缓存问题会导致一些莫名其妙的错误。

4.6 知识体系总览

为了让你对整个流程有个直观的认识,我画了一张图:

Flutter Module 源码依赖集成流程 步骤1 创建Flutter Module 步骤2 配置settings.gradle 步骤3 配置app/build.gradle 步骤4 同步与构建 常见错误排查 路径错误 / 版本不兼容 集成成功 Flutter页面可正常调用 核心要点 • 使用 --template module 创建 Flutter 模块 • settings.gradle 中正确配置 include_flutter.groovy 路径 • app/build.gradle 中依赖 :flutter 模块 • 遇到问题先双清(flutter clean + gradle clean)

这张图把整个流程串起来了。你跟着步骤走,基本不会出大问题。如果卡在某个环节,对照着图看看是哪一步没做对。

好了,源码依赖这种方式就讲到这里。说白了,核心就是三件事:创建模块、配置引用、添加依赖。只要把这三个环节搞明白,后面就顺了。


专注资料整理