记录一次 Flutter 升级遇到的问题

一、问题现象

最近将 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_64
  • armeabi-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。

3.35 相关PR GitHub链接


官方默认 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-v7a
  • arm64-v8a
  • x86_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 生命周期 + 执行顺序

执行顺序如下:

  1. Flutter 插件执行

    • abiFilters.clear()
    • 写入默认 ABI
  2. 然后执行 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 做这个调整?

可能原因包括:

  1. Play Store 强制 64 位支持
  2. 模拟器大量使用 x86_64
  3. CI 构建一致性
  4. 与 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
相关推荐
FFF-X5 分钟前
解决 Flutter Gradle 下载报错:修改默认 distributionUrl
flutter
程序员Ctrl喵20 小时前
异步编程:Event Loop 与 Isolate 的深层博弈
开发语言·flutter
前端不太难21 小时前
Flutter 如何设计可长期维护的模块边界?
flutter
小蜜蜂嗡嗡1 天前
flutter列表中实现置顶动画
flutter
始持1 天前
第十二讲 风格与主题统一
前端·flutter
始持1 天前
第十一讲 界面导航与路由管理
flutter·vibecoding
始持1 天前
第十三讲 异步操作与异步构建
前端·flutter
新镜1 天前
【Flutter】 视频视频源横向、竖向问题
flutter
黄林晴1 天前
Compose Multiplatform 1.10 发布:统一 Preview、Navigation 3、Hot Reload 三箭齐发
android·flutter
Swift社区1 天前
Flutter 应该按功能拆,还是按技术层拆?
flutter