You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多模块项目中Gradle插件生成flavorDimensions及productFlavors遇阻

解决AGP DSL锁定异常:跨模块生成Flavor配置

问题重现

开发的Gradle插件用于自动生成Android模块的flavorDimensions和productFlavors:

  • 直接将插件应用到Android模块时,功能正常;
  • 将插件应用到项目中其他非Android模块时,Gradle同步抛出AgpDslLockedException,提示无法修改flavorDimensions,因为配置已被读取锁定。

插件核心代码:

class MyPlugin : Plugin<Project> {
    override fun apply(project: Project) {
        // 遍历根项目所有子项目寻找Android模块
        project.rootProject.subprojects.forEach { subproject ->
            val android = subproject.extensions.findByName("android") as? AppExtension ?: return@forEach
            // 应用到非Android模块时触发异常
            android.flavorDimensions.add("dimension")
            android.productFlavors.create("flavor") { it.dimension = "dimension" }
        }
    }
}

异常信息:

It is too late to modify flavorDimensions.
It has already been read to configure this project.
Consider either moving this call to be during evaluation, or using the variant API.

问题原因

当插件应用到非Android模块(如other模块)时,遍历子项目执行修改操作的时机晚于Android模块的配置评估阶段。AGP会在项目评估完成后锁定DSL配置,禁止修改flavorDimensions这类会影响变体生成的核心配置。

解决方案

核心思路是:确保在Android插件应用后、DSL配置锁定前修改Flavor相关设置,通过监听子项目的Android插件加载事件实现。

修改后的插件代码:

import com.android.build.api.dsl.ApplicationExtension
import com.android.build.api.dsl.LibraryExtension
import org.gradle.api.Plugin
import org.gradle.api.Project

class MyPlugin : Plugin<Project> {
    override fun apply(project: Project) {
        // 监听所有子项目的Android插件应用事件
        project.rootProject.subprojects.forEach { subproject ->
            // 处理Android应用模块
            subproject.plugins.withId("com.android.application") {
                val android = subproject.extensions.getByType(ApplicationExtension::class.java)
                // 在插件刚加载时修改配置,此时DSL未锁定
                android.flavorDimensions.add("dimension")
                android.productFlavors.create("flavor") {
                    it.dimension = "dimension"
                }
            }

            // 可选:处理Android库模块
            subproject.plugins.withId("com.android.library") {
                val android = subproject.extensions.getByType(LibraryExtension::class.java)
                android.flavorDimensions.add("dimension")
                android.productFlavors.create("flavor") {
                    it.dimension = "dimension"
                }
            }
        }
    }
}

方案说明

  • 使用plugins.withId监听子项目中Android插件的加载事件,此时Android扩展已初始化,且DSL配置处于可修改状态;
  • 不管插件应用到项目中哪个模块,只要根项目下的子项目应用了Android插件,就会自动执行Flavor配置生成逻辑;
  • 避免了直接遍历子项目时因生命周期时机错误导致的DSL锁定异常。

补充说明

若之前尝试beforeEvaluate无效,大概率是因为未针对子项目的评估阶段操作,而是在插件所在模块的评估周期中执行,时机仍晚于Android模块的配置锁定点。上述方案通过绑定Android插件的加载事件,能精准命中安全修改时机。

内容的提问来源于stack exchange,提问作者Philipp Fahlteich

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 17:55:46