一、问题现象
最近将 Flutter SDK 从 3.29.x 升级到 3.38.10 版本 。
升级后发现:
📦 APK 打包体积变大了约 1.5 倍
随后定位到问题原因如下。
二、前提说明
升级前后以下配置均未发生变化:
- Gradle 版本:
8.14.2 - AGP 版本:
8.11.0(配置于settings.gradle.kts) - Flutter Gradle Plugin 版本:
1.0.0(配置于settings.gradle.kts) - 打包命令:
flutter build apk build.gradle.kts相关配置未变
原始 build.gradle.kts 配置
kotlin
// 原 build.gradle.kts 部分配置如下
buildTypes {
getByName("release") {
ndk {
abiFilters.addAll(listOf("arm64-v8a"))
}
}
}
原先通过修改 Gradle 配置,仅保留 arm64-v8a ABI,因此:
flutter build apk只会生成arm64-v8a的 APK
升级后的异常现象
升级到 3.38.10 后,在其他配置未变的情况下:
x86_64armeabi-v7a
也被打包进 APK。
随后开始排查原因。
修复方式
修改 build.gradle.kts:
kotlin
// 新 build.gradle.kts 部分配置如下
buildTypes {
getByName("release") {
ndk {
abiFilters.clear()
abiFilters.addAll(listOf("arm64-v8a"))
}
}
}
重新打包后恢复正常,仅包含 arm64-v8a。
三、问题原因分析
通过 GPT 了解到:
Flutter 3.35+ 之后,Flutter SDK 内部的 Flutter Gradle Plugin 实现发生变化,默认构建所有支持的 ABI。
官方默认 ABI
在 FlutterPluginConstants.kt 中可以看到:
kotlin
@JvmStatic val DEFAULT_PLATFORMS =
listOf(
PLATFORM_ARM32,
PLATFORM_ARM64,
PLATFORM_X86_64
)
对应架构映射:
kotlin
@JvmStatic val PLATFORM_ARCH_MAP =
mapOf(
PLATFORM_ARM32 to "armeabi-v7a",
PLATFORM_ARM64 to "arm64-v8a",
PLATFORM_X86_64 to "x86_64"
)
也就是说默认会构建:
armeabi-v7aarm64-v8ax86_64
四、插件内部逻辑
核心代码位于:
css
<flutter sdk>\packages\flutter_tools\gradle\src\main\kotlin
FlutterPlugin.kt 关键代码
kotlin
FlutterPluginUtils.getAndroidExtension(project).buildTypes.forEach { buildType ->
buildType.ndk.abiFilters.clear()
FlutterPluginConstants.DEFAULT_PLATFORMS.forEach { platform ->
val abiValue: String =
FlutterPluginConstants.PLATFORM_ARCH_MAP[platform]
?: throw GradleException("Invalid platform: $platform")
buildType.ndk.abiFilters.add(abiValue)
}
}
关键点:
插件会对
abiFilters先执行clear(),然后写入默认 ABI。
五、关于官方注释的理解
源码中有一句:
If the user has specified abiFilters in their build.gradle file, those settings will take precedence over these defaults.
翻译:
如果用户在
build.gradle中指定了abiFilters,则用户配置优先。
但从实际构建结果来看,并未覆盖默认值。
实际原因:Gradle 生命周期 + 执行顺序
执行顺序如下:
-
Flutter 插件执行
abiFilters.clear()- 写入默认 ABI
-
然后执行
build.gradle.kts中的:
kotlin
abiFilters.addAll(listOf("arm64-v8a"))
由于只是 addAll(),而不是 clear() 再添加,因此:
最终结果 = 默认 ABI + 配置的 ABI
更准确的理解
这句官方注释的真实含义应该是:
如果用户的配置能够在插件逻辑之后覆盖默认值(例如先
clear()再addAll()),那么用户配置才会真正生效。
六、关于 Flutter Gradle Plugin 版本的疑问
虽然在 settings.gradle.kts 中声明:
Flutter Gradle Plugin 1.0.0
但:
这个版本号并不代表实际插件实现版本。
真正的实现逻辑:
- 位于 Flutter SDK 内部
- 随 Flutter SDK 升级而变化
七、为什么 Flutter 做这个调整?
可能原因包括:
- Play Store 强制 64 位支持
- 模拟器大量使用
x86_64 - CI 构建一致性
- 与 App Bundle 行为统一
八、后续方案选择
方式一:通过 abiFilters 控制
缺点:
- Flutter 插件未来可能继续调整
- Gradle 层和 Flutter 层逻辑可能冲突
方式二:推荐方式
bash
flutter build apk --split-per-abi
优点:
- 官方推荐方式
- 构建逻辑清晰
- 不依赖 Gradle hack
缺点:
- 会生成多个 APK
- 构建时间增加
方式三:更适合我的方案
由于目标平台非常明确,仅支持 arm64-v8a:
bash
flutter build apk --target-platform android-arm64
优点:
- 只构建指定 ABI
- 构建时间最短
- 不依赖 Gradle 层配置
- 不受 Flutter 插件实现影响
总结
本次问题本质是:
Flutter 3.35+ 修改了内部 Gradle 插件逻辑,默认构建所有 ABI,并在插件执行阶段重写
abiFilters。
关键认知:
settings.gradle.kts中声明的插件版本 ≠ 实际实现版本addAll()不会覆盖默认 ABI- 必须
clear()后再添加 - 更推荐使用
--target-platform或--split-per-abi