使用 Gradle Convention Plugins(约定插件)优化 Android 编译配置

引言

维护一个拥有数十甚至上百个模块的大型 Android 项目很容易让人焦头烂额。不同团队负责不同功能模块,久而久之项目的构建逻辑就会逐渐"失控":各个模块依赖配置五花八门,插件应用方式参差不齐。

当遇到依赖库升级时,比如 Android发布新版本了、Kotlin版本要升级了、三方库出现 Breaking change 了等等,所有项目、所有模块都需要同步修改,而那些复制粘贴的重复构建逻辑早已散布在项目的各个角落。

但如果你的构建配置能够实现集中化、标准化和复用化呢?如果每个功能模块、核心库或主应用,只需应用一个插件就能自动遵循项目的统一规范呢?这正是 Gradle Convention Plugins (约定插件) 的用武之地。

这不就是 buildSrc 的用途吗?

虽然 buildSrc 曾经是集中管理 Gradle 逻辑的主流方案,但它有一个致命缺陷:buildSrc 目录下的任何修改,都会触发整个项目的全量重新构建------哪怕这个修改和绝大多数模块毫无关联。这对于大型 Android 项目来说,会严重拖慢构建速度。

而约定插件完美解决了这个问题:它的构建逻辑只需编译并缓存一次,就像普通插件一样运行,不会触发不必要的全量重构。同时,它更便于版本管理和测试,还能让你的build.gradle.kts 文件变得更简洁、更模块化。简而言之,约定插件既保留了集中式构建逻辑的所有优势,又避免了 buildSrc 带来的性能损耗。

快速上手

首先,创建一个名为 build-logic 的新目录,并在其中添加 settings.gradle.kts 文件:

kt 复制代码
pluginManagement {
    repositories {
        gradlePluginPortal()
        google()
    }
}

dependencyResolutionManagement {
    repositories {
        google {
            content {
                includeGroupByRegex("com\\.android.*")
                includeGroupByRegex("com\\.google.*")
                includeGroupByRegex("androidx.*")
            }
        }
        mavenCentral()
    }
    versionCatalogs {
        create("libs") {
            from(files("../gradle/libs.versions.toml"))
        }
    }
}

rootProject.name = "build-logic"
include(":convention")  

在这个文件中,我们注册约定模块。接下来,创建该模块并在其 build.gradle.kts 文件中添加如下配置:

kt 复制代码
import org.jetbrains.kotlin.gradle.dsl.JvmTarget

plugins {
    `kotlin-dsl`
}

group = "com.example.template.buildlogic"

java {
    sourceCompatibility = JavaVersion.VERSION_17
    targetCompatibility = JavaVersion.VERSION_17
}

kotlin {
    compilerOptions {
        jvmTarget = JvmTarget.JVM_17
    }
}

dependencies {
    compileOnly(libs.android.gradleApiPlugin)
    compileOnly(libs.kotlin.gradlePlugin)
    compileOnly(libs.compose.gradlePlugin)
    // Add any other needed external plugin like: KSP, Hilt, etc
    implementation(files(libs.javaClass.superclass.protectionDomain.codeSource.location)) // To allow getting version catalog references in convention plugins
}

gradlePlugin {
    plugins { // Here we will register our custom plugins
        // Android
        register("androidApplication") {
            id = libs.plugins.template.application.get().pluginId
            implementationClass = "ApplicationConventionPlugin"
        }
        register("androidLibrary") {
            id = libs.plugins.template.library.get().pluginId
            implementationClass = "LibraryConventionPlugin"
        }
        // JVM
        register("jvm") {
            id = libs.plugins.template.jvm.get().pluginId
            implementationClass = "JvmConventionPlugin"
        }
        // Compose
        register("androidComposeApplication") {
            id = libs.plugins.template.compose.application.get().pluginId
            implementationClass = "ComposeApplicationConventionPlugin"
        }
        register("androidComposeLibrary") {
            id = libs.plugins.template.compose.library.get().pluginId
            implementationClass = "ComposeLibraryConventionPlugin"
        }
        // Koin
        register("koinCore") {
            id = libs.plugins.template.koin.core.get().pluginId
            implementationClass = "KoinCoreConventionPlugin"
        }
        register("koinAndroid") {
            id = libs.plugins.template.koin.android.get().pluginId
            implementationClass = "KoinAndroidConventionPlugin"
        }
        // Flavors
        register("FlavorApplication") {
            id = libs.plugins.template.flavor.application.get().pluginId
            implementationClass = "FlavorApplicationConventionPlugin"
        }
        register("FlavorLibrary") {
            id = libs.plugins.template.flavor.library.get().pluginId
            implementationClass = "FlavorLibraryConventionPlugin"
        }
        // Build Types
        register("BuildTypeApplication") {
            id = libs.plugins.template.buildtype.application.get().pluginId
            implementationClass = "BuildTypeApplicationConventionPlugin"
        }
        register("BuildTypeLibrary") {
            id = libs.plugins.template.buildtype.library.get().pluginId
            implementationClass = "BuildTypeLibraryConventionPlugin"
        }
        // Architecture Layers
        register("ArchitectureLayerUIArchitectureLayer") {
            id = libs.plugins.template.ui.architecture.layer.get().pluginId
            implementationClass = "ArchitectureLayerUIConventionPlugin"
        }
        register("ArchitectureLayerDomainArchitectureLayer") {
            id = libs.plugins.template.domain.architecture.layer.get().pluginId
            implementationClass = "ArchitectureLayerDomainConventionPlugin"
        }
        register("ArchitectureLayerDataArchitectureLayer") {
            id = libs.plugins.template.data.architecture.layer.get().pluginId
            implementationClass = "ArchitectureLayerDataConventionPlugin"
        }
    }
}

dependencies 代码块中声明所有约定插件需要依赖的外部插件。实例中我们引入了 AndroidApplication, AndroidLibrary, Compose 等插件。如果你的项目使用其他插件(如 KSP、Hilt或Firebase),也需要在此处添加相应依赖。同时,这些插件必须在项目根目录的 build.gradle.kts 文件中声明:

kotlin 复制代码
plugins {
    alias(libs.plugins.kotlin.jvm) apply false
    alias(libs.plugins.android.application) apply false
    alias(libs.plugins.android.library) apply false
    alias(libs.plugins.kotlin.android) apply false
    alias(libs.plugins.kotlin.compose) apply false
}

plugins 代码块中,我们注册所有自定义约定插件,这些插件将在各个模块中复用。

重要提示:如果在此处列出了某个约定插件,但实际并未实现它,Gradle 构建过程会直接失败。每个约定插件都必须满足两个条件:

  1. 在 build-logic 模块中有对应的插件实现类
  2. 在版本目录文件(libs.versions.toml)中有对应的配置项,确保项目能正确解析和应用该插件

缺少任何一个条件,构建都会因 Gradle 无法找到插件而崩溃。

最后,别忘了在项目根目录的 settings.gradle.kts 文件中引入 build-logic 模块:

复制代码
pluginManagement {
    includeBuild("build-logic") <- Add here
    repositories {
        google {
            content {
                includeGroupByRegex("com\\.android.*")
                includeGroupByRegex("com\\.google.*")
                includeGroupByRegex("androidx.*")
            }
        }
        mavenCentral()
        gradlePluginPortal()
    }
}
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
    }
}

rootProject.name = "Template"

// Application
include(":app")
// Core
include(":core:designsystem")
// Features
/// Auth
include(":feature:auth:data")
include(":feature:auth:domain")
include(":feature:auth:ui")

通过配置提升构建速度

要优化整个项目的构建性能,可以在根目录的 gradle.properties 文件中添加以下配置项:

kt 复制代码
# Run independent tasks in parallel to speed up multi-module builds
org.gradle.parallel=true
# Reuse outputs from previous builds to avoid re-running tasks unnecessarily
org.gradle.caching=true
# Configure only the modules required for the current build, reducing configuration time
org.gradle.configureondemand=true
# Cache the result of the configuration phase so future builds can skip it entirely
org.gradle.configuration-cache=true
# Allow configuration caching work to run in parallel for even faster setup
org.gradle.configuration-cache.parallel=true

创建 Application 和 Library 的约定插件

首先需要创建的是用于配置应用模块和库模块的约定插件。

大多数项目只有一个应用模块,但使用约定插件可以为未来扩展预留空间------比如你可能需要添加第二个共享核心功能的应用。

而库模块则广泛应用于整个项目,既包括设计系统、网络请求、数据库等核心层模块,也涵盖各个业务功能模块。

Application 约定插件
kt 复制代码
import com.android.build.api.dsl.ApplicationExtension
import com.example.template.configureAndroid
import org.gradle.accessors.dm.LibrariesForLibs
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.getByType
import org.gradle.kotlin.dsl.the

class ApplicationConventionPlugin : Plugin<Project> {
    override fun apply(target: Project) {
        with(target) {
            val libs = the<LibrariesForLibs>()
            apply(plugin = libs.plugins.android.application.get().pluginId)
            apply(plugin = libs.plugins.kotlin.android.get().pluginId)

            val extension = extensions.getByType<ApplicationExtension>()
            configureAndroid(extension)
        }
    }
}
Library 约定插件
kt 复制代码
import com.android.build.api.dsl.LibraryExtension
import com.example.template.configureAndroid
import org.gradle.accessors.dm.LibrariesForLibs
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.getByType
import org.gradle.kotlin.dsl.the

class LibraryConventionPlugin : Plugin<Project> {
    override fun apply(target: Project) {
        with(target) {
            val libs = the<LibrariesForLibs>()
            apply(plugin = libs.plugins.android.library.get().pluginId)
            apply(plugin = libs.plugins.kotlin.android.get().pluginId)

            val extension = extensions.getByType<LibraryExtension>()
            configureAndroid(extension)
        }
    }
}

这两个插件都将共享配置委托给 ConfigureAndroid.kt 文件中定义的 configureAndroid 函数。该函数接收对应的通用扩展参数(应用模块对应 ApplicationExtension,库模块对应 LibraryExtension)。

在这个函数中,我们集中管理Android的关键配置:compileSdkminSdk,以及(仅针对应用模块的)targetSdk

同时,我们还会调用两个额外的配置函数:来自 ConfigureJava.ktconfigureJavaAndroid,以及来自 ConfigureKotlin.kt的configureKotlin

kt 复制代码
package com.example.template

import com.android.build.api.dsl.ApplicationExtension
import com.android.build.api.dsl.CommonExtension
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension

internal fun Project.configureAndroid(
    commonExtension: CommonExtension<*, *, *, *, *, *>,
) {
    commonExtension.apply {
        compileSdk = 36
        defaultConfig.minSdk = 24

        if (this is ApplicationExtension) {
            defaultConfig.targetSdk = 36
        }
    }

    configureJavaAndroid(commonExtension)
    configureKotlin<KotlinAndroidProjectExtension>()
}

ConfigureJava.kt 文件包含两个函数:configureJavaAndroid 用于 Android 模块,而 configureJavaJvm 则适用于纯 Kotlin 模块(比如包含用例、仓库接口和数据模型的领域层模块),这些模块不依赖 Android 框架。

kt 复制代码
package com.example.template

import com.android.build.api.dsl.CommonExtension
import org.gradle.api.JavaVersion
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.kotlin.dsl.configure

private val javaVersion = JavaVersion.VERSION_11

internal fun Project.configureJavaAndroid(commonExtension: CommonExtension<*, *, *, *, *, *>) {
    commonExtension.compileOptions {
        sourceCompatibility = javaVersion
        targetCompatibility = javaVersion
    }
}

internal fun Project.configureJavaJvm() {
    extensions.configure<JavaPluginExtension> {
        sourceCompatibility = javaVersion
        targetCompatibility = javaVersion
    }
}

最后,ConfigureKotlin.kt 提供了一个专门用于配置 Kotlin 编译器的函数。

完成插件实现后,我们需要在版本目录文件中声明这些约定插件,确保 Gradle 能够正确解析:

toml 复制代码
template-application = { id = "template.application" }
template-library = { id = "template.library" }

添加到版本目录后,在 build-logic 模块的 build.gradle.kts 文件的 gradlePlugin 代码块中注册这些插件:

kotlin 复制代码
gradlePlugin {
    plugins {
        // Android
        register("androidApplication") {
            id = libs.plugins.template.application.get().pluginId
            implementationClass = "ApplicationConventionPlugin"
        }
        register("androidLibrary") {
            id = libs.plugins.template.library.get().pluginId
            implementationClass = "LibraryConventionPlugin"
        }
        
        .....
    }
}

产品风味管理

项目如果需要配置产品风味(product flavors),也需要创建对应的约定插件。和构建类型一样,我们需要为应用模块和库模块分别创建插件,并通过 commonExtension 参数调用共享配置函数。

Application Flavor 约定插件
kt 复制代码
import com.android.build.api.dsl.ApplicationExtension
import com.example.template.configureFlavor
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.getByType

class FlavorApplicationConventionPlugin : Plugin<Project> {
    override fun apply(target: Project) {

        with(target) {
            val extension = extensions.getByType<ApplicationExtension>()
            configureFlavor(extension)
        }
    }
}
Library Flavor 约定插件
kt 复制代码
import com.android.build.api.dsl.LibraryExtension
import com.example.template.configureFlavor
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.getByType

class FlavorLibraryConventionPlugin : Plugin<Project> {
    override fun apply(target: Project) {

        with(target) {
            val extension = extensions.getByType<LibraryExtension>()
            configureFlavor(extension)
        }
    }
}
Flavors 公共配置
kt 复制代码
package com.example.template

import com.android.build.api.dsl.CommonExtension
import org.gradle.api.Project

private data class Dimension(val name: String, val values: List<String>)

private val environmentDimension = Dimension(
    name = "environment",
    values = listOf("dev", "prod"),
)

internal fun Project.configureFlavor(
    commonExtension: CommonExtension<*, *, *, *, *, *>,
) {
    commonExtension.apply {
        flavorDimensions += environmentDimension.name

        productFlavors {
            environmentDimension.values.forEach { value ->
                register(value) {
                    dimension = environmentDimension.name
                }
            }
        }
    }
}

Compose 配置

接下来,我们创建Compose相关的约定插件。同样的,需要两个插件(应用模块和库模块各一个),再加上一个共享的通用配置函数。

Application Compose 约定插件

在这个插件中,我们添加了Compose Activity所需的依赖。这些依赖没有放在库插件中,因为我们遵循单Activity架构原则。

注:如果你的项目需要在库模块中使用Activity组件,可以将这些依赖移到通用配置中。

kt 复制代码
import com.android.build.api.dsl.ApplicationExtension
import com.example.template.configureCompose
import org.gradle.accessors.dm.LibrariesForLibs
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.dependencies
import org.gradle.kotlin.dsl.getByType
import org.gradle.kotlin.dsl.the

class ComposeApplicationConventionPlugin : Plugin<Project> {
    override fun apply(target: Project) {

        with(target) {
            val libs = the<LibrariesForLibs>()
            apply(plugin = libs.plugins.kotlin.compose.get().pluginId)

            val extension = extensions.getByType<ApplicationExtension>()
            configureCompose(extension)

            dependencies {
                "implementation"(libs.androidx.activity.compose)
            }
        }
    }
}
Library Compose 约定插件
kt 复制代码
import com.android.build.api.dsl.LibraryExtension
import com.example.template.configureCompose
import org.gradle.accessors.dm.LibrariesForLibs
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.getByType
import org.gradle.kotlin.dsl.the

class ComposeLibraryConventionPlugin : Plugin<Project> {
    override fun apply(target: Project) {

        with(target) {
            val libs = the<LibrariesForLibs>()
            apply(plugin = libs.plugins.kotlin.compose.get().pluginId)

            val extension = extensions.getByType<LibraryExtension>()
            configureCompose(extension)
        }
    }
}
Compose 通用配置

通用配置负责处理 Compose 的共享设置,包括 Compose BOM 以及从版本目录中引入的其他依赖:

kt 复制代码
package com.example.template

import com.android.build.api.dsl.CommonExtension
import org.gradle.accessors.dm.LibrariesForLibs
import org.gradle.api.Project
import org.gradle.kotlin.dsl.dependencies
import org.gradle.kotlin.dsl.the

internal fun Project.configureCompose(
    commonExtension: CommonExtension<*, *, *, *, *, *>,
) {
    commonExtension.apply {
        val libs = the<LibrariesForLibs>()

        buildFeatures {
            compose = true
        }

        dependencies {
            "implementation"(platform(libs.androidx.compose.bom))
            "implementation"(libs.androidx.compose.ui)
            "implementation"(libs.androidx.compose.ui.graphics)
            "implementation"(libs.androidx.compose.ui.tooling.preview)
            "implementation"(libs.androidx.compose.material3)
            "androidTestImplementation"(platform(libs.androidx.compose.bom))
            "androidTestImplementation"(libs.androidx.compose.ui.test.junit4)
            "debugImplementation"(libs.androidx.compose.ui.tooling)
            "debugImplementation"(libs.androidx.compose.ui.test.manifest)
        }
    }
}

Koin 依赖注入配置

接下来,我们用Koin配置依赖注入。这里我们创建两个约定插件,但划分依据不是应用模块或库模块,而是模块的类型:

  1. Android模块
  2. 核心(纯Kotlin)模块

这里没有通用配置函数,因为我们只为每种模块类型添加特定的依赖。

Koin Android 约定插件

kt 复制代码
import org.gradle.accessors.dm.LibrariesForLibs
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.dependencies
import org.gradle.kotlin.dsl.the

class KoinAndroidConventionPlugin : Plugin<Project> {
    override fun apply(target: Project) {

        with(target) {
            val libs = the<LibrariesForLibs>()

            dependencies {
                "implementation"(project.dependencies.platform(libs.koin.bom))
                "implementation"(libs.koin.android)
                "testImplementation"(libs.koin.android.test)
                "testImplementation"(libs.koin.junit4)
            }
        }
    }
}

Koin Coin 约定插件

kt 复制代码
import org.gradle.accessors.dm.LibrariesForLibs
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.dependencies
import org.gradle.kotlin.dsl.the

class KoinCoreConventionPlugin : Plugin<Project> {
    override fun apply(target: Project) {

        with(target) {
            val libs = the<LibrariesForLibs>()

            dependencies {
                "implementation"(project.dependencies.platform(libs.koin.bom))
                "implementation"(libs.koin.core)
                "testImplementation"(libs.koin.test)
                "testImplementation"(libs.koin.junit4)
            }
        }
    }
}

版本目录 (Version Catalog

)

别忘了在版本目录文件(libs.versions.toml)中声明所有约定插件需要的依赖。

复制代码
[versions]
agp = "8.13.0"
kotlin = "2.2.21"
kotlin-serialization-json = "1.9.0"
coreKtx = "1.17.0"
junit = "4.13.2"
junitVersion = "1.3.0"
espressoCore = "3.7.0"
lifecycleRuntimeKtx = "2.10.0"
composeActivity = "1.12.0"
composeBom = "2025.11.01"
ksp = "2.2.20-2.0.4"
koin-bom = "4.1.1"
ktor-bom = "3.3.2"
navigation = "2.9.6"

[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" }

# Kotlin
kotlin-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlin-serialization-json" }

# Compose
androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "composeActivity" }
androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigation" }
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
androidx-compose-ui = { group = "androidx.compose.ui", name = "ui" }
androidx-compose-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
androidx-compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
androidx-compose-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
androidx-compose-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" }

# Koin
koin-bom = { module = "io.insert-koin:koin-bom", version.ref = "koin-bom" }
koin-core = { module = "io.insert-koin:koin-core" }
koin-android = { module = "io.insert-koin:koin-android" }
koin-android-compose = { module = "io.insert-koin:koin-androidx-compose" }
koin-android-compose-navigation = { module = "io.insert-koin:koin-androidx-compose-navigation" }
koin-test = { module = "io.insert-koin:koin-test" }
koin-android-test = { module = "io.insert-koin:koin-android-test" }
koin-junit4 = { module = "io.insert-koin:koin-test-junit4" }

# Ktor
ktor-bom = { module = "io.ktor:ktor-bom", version.ref = "ktor-bom" }
ktor-core = { module = "io.ktor:ktor-client-core" }
ktor-client-cio = { module = "io.ktor:ktor-client-cio" }
ktor-client-logging = { module = "io.ktor:ktor-client-logging" }
ktor-content-negotiation = { module = "io.ktor:ktor-client-content-negotiation" }
ktor-serialization-json = { module = "io.ktor:ktor-serialization-kotlinx-json" }

# Dependencies of the included build-logic
android-gradleApiPlugin = { group = "com.android.tools.build", name = "gradle-api", version.ref = "agp" }
compose-gradlePlugin = { module = "org.jetbrains.kotlin:compose-compiler-gradle-plugin", version.ref = "kotlin" }
kotlin-gradlePlugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin" }
ksp-gradlePlugin = { group = "com.google.devtools.ksp", name = "com.google.devtools.ksp.gradle.plugin", version.ref = "ksp" }

[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
android-library = { id = "com.android.library", version.ref = "agp" }
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }

# Plugins included build-logic
template-application = { id = "template.application" }
template-library = { id = "template.library" }
template-jvm = { id = "template.jvm" }
template-kotlin-serialization = { id = "template.kotlin.serialization" }
template-compose-application = { id = "template.compose.application" }
template-compose-library = { id = "template.compose.library" }
template-koin-core = { id = "template.koin.core" }
template-koin-android = { id = "template.koin.android" }
template-flavor-application = { id = "template.flavor.application" }
template-flavor-library = { id = "template.flavor.library" }
template-buildtype-application = { id = "template.buildtype.application" }
template-buildtype-library = { id = "template.buildtype.library" }
template-ui-architecture-layer = { id = "template.ui.architecture.layer" }
template-data-architecture-layer = { id = "template.data.architecture.layer" }
template-domain-architecture-layer = { id = "template.domain.architecture.layer" }

在模块中应用插件

所有约定插件都定义完成后,就可以在应用模块中使用了。

例如,我们可以将原来冗长的配置:

kt 复制代码
plugins {
    alias(libs.plugins.android.application)
    alias(libs.plugins.kotlin.android)
    alias(libs.plugins.kotlin.compose)
}

android {
    namespace = "com.example.template"
    compileSdk = 36

    defaultConfig {
        applicationId = "com.example.template"
        minSdk = 24
        targetSdk = 36
        versionCode = 1
        versionName = "1.0"

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            isMinifyEnabled = false
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_11
        targetCompatibility = JavaVersion.VERSION_11
    }
    kotlinOptions {
        jvmTarget = "11"
    }
    buildFeatures {
        compose = true
    }
}

dependencies {
    implementation(libs.androidx.core.ktx)
    implementation(libs.androidx.lifecycle.runtime.ktx)
    implementation(libs.androidx.activity.compose)
    implementation(platform(libs.androidx.compose.bom))
    implementation(libs.androidx.compose.ui)
    implementation(libs.androidx.compose.ui.graphics)
    implementation(libs.androidx.compose.ui.tooling.preview)
    implementation(libs.androidx.compose.material3)
    testImplementation(libs.junit)
    androidTestImplementation(libs.androidx.junit)
    androidTestImplementation(libs.androidx.espresso.core)
    androidTestImplementation(platform(libs.androidx.compose.bom))
    androidTestImplementation(libs.androidx.compose.ui.test.junit4)
    debugImplementation(libs.androidx.compose.ui.tooling)
    debugImplementation(libs.androidx.compose.ui.test.manifest)
}

(示例中省略了风味和 Kotlin 选项的配置,实际的 build.gradle.kts 文件会更加庞大)

简化为使用约定插件的简洁配置:

kt 复制代码
plugins {
    alias(libs.plugins.template.application)
    alias(libs.plugins.template.compose.application)
    alias(libs.plugins.template.flavor.application)
    alias(libs.plugins.template.buildtype.application)
    alias(libs.plugins.template.koin.android)
}

android {
    namespace = "com.example.template"

    defaultConfig {
        applicationId = "com.example.template"
        versionCode = 1
        versionName = "1.0"

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
    }
}

这种方式不仅实现了构建逻辑的集中管理,减少了代码重复,还让后续跨模块的更新维护变得异常轻松。

相关推荐
松仔log12 小时前
Java中级——组合和继承
android·java·开发语言
我命由我1234515 小时前
Jetpack Compose - MaterialExpressiveTheme 与 MaterialTheme、ColorScheme
android·java·开发语言·java-ee·kotlin·android jetpack·android runtime
lilian23316 小时前
Harmony os 技术实战|拼豆制图06:收藏 ID、生成记录与重启恢复怎么不打架
android·java·数据库·harmonyos
2601_9557596216 小时前
ClaudeAPI成本中心与业务标签设计指南
android·java·数据库
余衫马16 小时前
2026最新版!Android Studio 极速安装与配置指南
android·ide·android studio
AFinalStone16 小时前
Android 7系统异常问题排查(五)Framework层(下)—System Server崩溃
android·tombstone·系统异常
AFinalStone16 小时前
Android 7系统异常问题排查(八)系统追踪—Trace机制与性能诊断
android·系统异常
极客猴子20 小时前
Android录音转写频繁卡顿?多款APP长时间会议场景稳定性实测
android·人工智能·智能手机·飞书
Kapaseker20 小时前
Boolean 变量到底该怎么命名?
android·kotlin
AFinalStone20 小时前
Android 7系统异常问题排查(六)应用异常(上)—ANR机制全解
android·系统异常