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分钟以内。

核心结论: 正式项目请用Flutter Module方式。源码依赖只适合你一个人玩的时候用。

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 getflutter 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依赖。其他第三方库按需添加。
我的经验: 在Module里尽量少加第三方库。因为每个库都会增加编译时间和包体积。我一般只加 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。

避坑指南: 我曾经遇到一个问题,集成后Android编译报错 Could not find method setBinding()。后来发现是 settings.gradle 的写法不对。正确的做法是:setBinding 必须在 include ':app' 之后调用,否则Gradle找不到项目。

3.6 知识体系图

下面我用一张SVG图,把整个集成流程串起来。你看完应该就清楚了:

Flutter Module 集成流程 Flutter Module lib/main.dart (Dart代码) pubspec.yaml (依赖配置) .android/ (壳工程) include_flutter.groovy flutter build aar → .aar文件 Android项目 settings.gradle (添加binding) app/build.gradle (依赖flutter) Java/Kotlin代码 (调用Flutter) FlutterEngine + FlutterFragment 编译 → APK/AAB 核心:Flutter Module通过include_flutter.groovy暴露给Android,Android通过project(':flutter')引用

3.7 验证集成是否成功

集成完之后,怎么验证?我一般做三步检查:

  1. 编译检查 — 在Android项目根目录执行 ./gradlew assembleDebug,看能否编译通过。
  2. 运行检查 — 在Android Studio里直接运行App,看Flutter页面能否正常显示。
  3. 热重载检查 — 修改Flutter代码,看Android端能否实时更新。如果能,说明集成成功。
小技巧: 如果编译报错 Flutter engine not found,多半是Flutter SDK路径没配置对。检查一下 local.properties 里的 flutter.sdk 路径是否正确。

好了,这一章的内容就到这里。你跟着做一遍,应该就能把Flutter Module集成到Android项目里了。下一章我们会讲如何在Android代码里启动Flutter页面,以及如何传递数据。


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