xDocxDoc
AI
前端
后端
iOS
Android
Flutter
AI
前端
后端
iOS
Android
Flutter
  • 为多模块Android项目创建可维护的Gradle脚本

为多模块Android项目创建可维护的Gradle脚本

构建和维护多模块Android项目是一项复杂任务,Gradle脚本的质量直接影响到团队的开发效率和项目的长期健康。本文将深入探讨如何利用Gradle Kotlin DSL、自定义插件和现代化工具链来创建高度可维护的构建配置。

1. 多模块项目结构的重要性

Android多模块项目通过关注点分离原则将代码库划分为多个独立模块,每个模块承担特定职责。这种架构显著提高了代码的可维护性、可测试性和构建性能。

典型的多模块结构包括:

  • App模块: 应用入口点,整合所有功能模块
  • Core模块: 提供共享工具、扩展和基础组件
  • Feature模块: 实现特定功能(如认证、仪表板)
  • Data模块: 处理数据访问和持久化
  • Domain模块: 包含业务逻辑和用例

在settings.gradle文件中定义模块结构:

// settings.gradle (root)
include ':app', ':core', ':feature-auth', ':feature-dashboard', ':data', ':domain'

2. Gradle Kotlin DSL的优势

Kotlin DSL为Gradle构建脚本带来了类型安全、更好的IDE支持和增强的可读性。研究表明,使用Kotlin DSL可以将构建脚本错误减少30%,并使新团队成员的上手时间缩短25%。

2.1 类型安全的构建脚本

Kotlin DSL提供编译时类型检查,显著减少运行时错误:

// 传统Groovy方式(无类型安全)
android {
    compileSdkVersion 30
}

// Kotlin DSL方式(类型安全)
android {
    compileSdk = 30
}

2.2 增强的IDE支持

Kotlin DSL享受完整的IDE功能支持:

  • 自动补全和代码导航
  • 重构工具支持
  • 错误高亮和快速修复
  • 文档悬停提示

2.3 更好的可读性和维护性

Kotlin DSL使构建脚本更加简洁和表达性强:

dependencies {
    implementation(libs.androidx.core.ktx)
    implementation(libs.androidx.compose.ui)
    testImplementation(libs.junit)
    
    // 模块依赖
    implementation(project(":core"))
    implementation(project(":feature-auth"))
}

3. 创建自定义Gradle插件

自定义Gradle插件是集中化构建逻辑和减少样板代码的关键手段。通过创建应用级和模块级插件,可以统一管理所有模块的配置。

3.1 建立buildSrc模块

buildSrc是一个特殊的Gradle模块,用于托管构建逻辑和自定义插件:

  1. 创建buildSrc目录:在项目根目录下创建buildSrc文件夹
  2. 配置build.gradle.kts:
// buildSrc/build.gradle.kts
plugins {
    `java-gradle-plugin`
    `kotlin-dsl`
    id("maven-publish")
}

repositories {
    google()
    mavenCentral()
    gradlePluginPortal()
}

dependencies {
    implementation("com.android.tools.build:gradle:8.1.0")
    implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.20")
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.20")
}

gradlePlugin {
    plugins {
        register("android-app-plugin") {
            id = "android-app-plugin"
            implementationClass = "AndroidAppPlugin"
        }
        register("android-library-plugin") {
            id = "android-library-plugin"
            implementationClass = "AndroidLibraryPlugin"
        }
    }
}
  1. 在settings.gradle中包含buildSrc:
// settings.gradle.kts
includeBuild("buildSrc")

3.2 实现应用级插件

应用级插件专门用于配置Android应用模块:

// buildSrc/src/main/kotlin/AndroidAppPlugin.kt
import com.android.build.api.dsl.ApplicationExtension
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.configure

class AndroidAppPlugin : Plugin<Project> {
    override fun apply(project: Project) = with(project) {
        with(pluginManager) {
            apply("com.android.application")
            apply("org.jetbrains.kotlin.android")
        }
        
        extensions.configure<ApplicationExtension> {
            configureAndroidCommonSettings(this)
            configureApplicationSpecificSettings(this)
        }
        
        configureDependencies()
    }
    
    private fun configureApplicationSpecificSettings(extension: ApplicationExtension) {
        extension.defaultConfig {
            applicationId = "com.example.myapp"
            versionCode = 1
            versionName = "1.0.0"
            
            // 配置自定义字段
            buildConfigField("String", "API_BASE_URL", "\"https://api.example.com\"")
            buildConfigField("boolean", "LOGGING_ENABLED", "true")
        }
        
        extension.buildTypes {
            getByName("debug") {
                isDebuggable = true
                isMinifyEnabled = false
                applicationIdSuffix = ".debug"
            }
            
            getByName("release") {
                isDebuggable = false
                isMinifyEnabled = true
                isShrinkResources = true
                proguardFiles(
                    getDefaultProguardFile("proguard-android-optimize.txt"),
                    "proguard-rules.pro"
                )
            }
            
            create("staging") {
                initWith(getByName("debug"))
                applicationIdSuffix = ".staging"
                matchingFallbacks += "debug"
            }
        }
        
        extension.productFlavors {
            create("free") {
                dimension = "version"
                applicationIdSuffix = ".free"
                versionNameSuffix = "-free"
            }
            create("paid") {
                dimension = "version"
                applicationIdSuffix = ".paid"
                versionNameSuffix = "-paid"
            }
        }
    }
    
    private fun Project.configureDependencies() {
        dependencies.run {
            // 公共依赖
            add("implementation", libs.androidx.core.ktx)
            add("implementation", libs.androidx.appcompat)
            add("implementation", libs.material)
            
            // 测试依赖
            add("testImplementation", libs.junit)
            add("androidTestImplementation", libs.androidx.junit)
            add("androidTestImplementation", libs.androidx.espresso.core)
        }
    }
}

3.3 实现库模块插件

库模块插件为Android库模块提供统一配置:

// buildSrc/src/main/kotlin/AndroidLibraryPlugin.kt
import com.android.build.api.dsl.LibraryExtension
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.configure

class AndroidLibraryPlugin : Plugin<Project> {
    override fun apply(project: Project) = with(project) {
        with(pluginManager) {
            apply("com.android.library")
            apply("org.jetbrains.kotlin.android")
        }
        
        extensions.configure<LibraryExtension> {
            configureAndroidCommonSettings(this)
            configureLibrarySpecificSettings(this)
        }
        
        configureDependencies()
    }
    
    private fun configureLibrarySpecificSettings(extension: LibraryExtension) {
        extension.buildTypes {
            getByName("debug") {
                isMinifyEnabled = false
            }
            
            getByName("release") {
                isMinifyEnabled = true
                consumerProguardFiles("proguard-rules.pro")
            }
        }
        
        // 配置发布选项
        extension.publishing {
            singleVariant("release") {
                withSourcesJar()
                withJavadocJar()
            }
        }
    }
    
    private fun Project.configureDependencies() {
        dependencies.run {
            // 公共依赖
            add("implementation", libs.androidx.core.ktx)
            
            // 测试依赖
            add("testImplementation", libs.junit)
            add("androidTestImplementation", libs.androidx.junit)
        }
    }
}

// 公共Android配置扩展函数
fun configureAndroidCommonSettings(extension: CommonExtension<*>) {
    extension.compileSdk = 34
    
    extension.defaultConfig {
        minSdk = 24
        targetSdk = 34
        
        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
        
        // 公共ProGuard配置
        consumerProguardFiles("consumer-rules.pro")
    }
    
    extension.compileOptions {
        sourceCompatibility = JavaVersion.VERSION_11
        targetCompatibility = JavaVersion.VERSION_11
    }
    
    extension.kotlinOptions {
        jvmTarget = "11"
        freeCompilerArgs = freeCompilerArgs + listOf(
            "-Xopt-in=kotlin.RequiresOptIn",
            "-Xjvm-default=all"
        )
    }
    
    extension.buildFeatures {
        compose = true
        buildConfig = true
    }
    
    extension.composeOptions {
        kotlinCompilerExtensionVersion = "1.5.1"
    }
    
    extension.packagingOptions {
        resources {
            excludes += "/META-INF/{AL2.0,LGPL2.1}"
            excludes += "META-INF/LICENSE.md"
            excludes += "META-INF/LICENSE-notice.md"
        }
    }
}

3.4 使用自定义插件

在模块的build.gradle.kts文件中应用自定义插件:

// app/build.gradle.kts
plugins {
    id("android-app-plugin")
}

android {
    namespace = "com.example.myapp"
    
    // 可以覆盖插件中的默认配置
    defaultConfig {
        versionCode = 2
        versionName = "1.0.1"
    }
}

dependencies {
    // 添加模块特定依赖
    implementation(project(":core"))
    implementation(project(":feature-auth"))
    implementation(project(":feature-dashboard"))
    
    // 添加模块特定第三方依赖
    implementation(libs.retrofit)
    implementation(libs.okhttp.logging)
}
// feature-auth/build.gradle.kts
plugins {
    id("android-library-plugin")
}

android {
    namespace = "com.example.feature.auth"
}

dependencies {
    implementation(project(":core"))
    implementation(libs.androidx.compose.ui)
    implementation(libs.koin.android)
}

4. 版本目录管理

Gradle版本目录(Version Catalogs)提供了中心化的依赖管理方案,显著减少版本冲突和维护负担。

4.1 配置版本目录

在gradle目录下创建libs.versions.toml文件:

# gradle/libs.versions.toml
[versions]
agp = "8.1.0"
kotlin = "1.8.20"
compileSdk = "34"
minSdk = "24"
targetSdk = "34"

junit = "4.13.2"
androidx-junit = "1.1.5"
espresso-core = "3.5.1"

core-ktx = "1.10.1"
appcompat = "1.6.1"
material = "1.9.0"
compose-bom = "2023.08.00"
lifecycle-runtime-ktx = "2.6.1"
activity-compose = "1.7.2"

retrofit = "2.9.0"
okhttp = "4.11.0"
koin-android = "3.4.3"

[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "core-ktx" }
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
androidx-material = { group = "com.google.android.material", name = "material", version.ref = "material" }

androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" }
androidx-compose-ui = { group = "androidx.compose.ui", name = "compose-ui" }
androidx-compose-ui-graphics = { group = "androidx.compose.ui", name = "compose-ui-graphics" }
androidx-compose-ui-tooling = { group = "androidx.compose.ui", name = "compose-ui-tooling" }
androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "compose-ui-tooling-preview" }
androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" }

androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycle-runtime-ktx" }
androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activity-compose" }

retrofit = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit" }
retrofit-converter-gson = { group = "com.squareup.retrofit2", name = "retrofit-converter-gson", version.ref = "retrofit" }
okhttp = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhttp" }
okhttp-logging = { group = "com.squareup.okhttp3", name = "logging-interceptor", version.ref = "okhttp" }

koin-android = { group = "io.insert-koin", name = "koin-android", version.ref = "koin-android" }
koin-androidx-compose = { group = "io.insert-koin", name = "koin-androidx-compose", version.ref = "koin-android" }

[bundles]
androidx-compose = [
    "androidx-compose-ui",
    "androidx-compose-ui-graphics",
    "androidx-compose-ui-tooling",
    "androidx-compose-ui-tooling-preview",
    "androidx-compose-material3"
]

androidx-essentials = [
    "androidx-core-ktx",
    "androidx-lifecycle-runtime-ktx",
    "androidx-activity-compose"
]

network = [
    "retrofit",
    "retrofit-converter-gson",
    "okhttp",
    "okhttp-logging"
]

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

4.2 在构建脚本中使用版本目录

版本目录可以通过类型安全的方式在构建脚本中访问:

// 在build.gradle.kts中使用版本目录
dependencies {
    // 使用单个依赖
    implementation(libs.androidx.core.ktx)
    implementation(libs.retrofit)
    
    // 使用依赖包
    implementation(libs.bundles.androidx.compose)
    implementation(libs.bundles.network)
    
    // 测试依赖
    testImplementation(libs.junit)
    androidTestImplementation(libs.bundles.androidx.test)
}

4.3 在自定义插件中使用版本目录

在自定义插件中访问版本目录需要特殊处理:

// 扩展函数用于访问版本目录
fun Project.getLibs(): VersionCatalog {
    return extensions.getByType<VersionCatalogsExtension>().named("libs")
}

// 在插件中使用版本目录
class AndroidAppPlugin : Plugin<Project> {
    override fun apply(project: Project) = with(project) {
        val libs = getLibs()
        
        extensions.configure<ApplicationExtension> {
            defaultConfig {
                minSdk = libs.findVersion("minSdk").get().requiredVersion.toInt()
                targetSdk = libs.findVersion("targetSdk").get().requiredVersion.toInt()
            }
        }
        
        dependencies.apply {
            add("implementation", libs.findLibrary("androidx.core.ktx").get())
            add("implementation", libs.findLibrary("androidx.compose.ui").get())
        }
    }
}

5. 高级构建配置

5.1 构建变体和产品风味

多模块项目通常需要复杂的构建变体配置:

android {
    flavorDimensions += listOf("version", "environment")
    
    productFlavors {
        create("free") {
            dimension = "version"
            applicationIdSuffix = ".free"
        }
        create("paid") {
            dimension = "version"
            applicationIdSuffix = ".paid"
        }
        
        create("dev") {
            dimension = "environment"
            buildConfigField("String", "API_URL", "\"https://dev.api.example.com\"")
        }
        create("staging") {
            dimension = "environment"
            buildConfigField("String", "API_URL", "\"https://staging.api.example.com\"")
        }
        create("prod") {
            dimension = "environment"
            buildConfigField("String", "API_URL", "\"https://api.example.com\"")
        }
    }
    
    // 配置变体过滤器
    variantFilter {
        ignore = buildType.name == "release" && 
                flavors.any { it.name == "dev" }
    }
    
    // 配置源集
    sourceSets {
        getByName("freeDev") {
            java.srcDirs("src/free/java")
        }
        getByName("paidProd") {
            res.srcDirs("src/paid/res")
        }
    }
}

5.2 构建优化技术

实施构建优化可以显著减少构建时间:

// gradle.properties中配置构建优化
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.daemon=true
org.gradle.configureondemand=true
android.enableBuildCache=true

# 内存配置
org.gradle.jvmargs=-Xmx4096m -XX:MaxMetaspaceSize=1024m -XX:+HeapDumpOnOutOfMemoryError
kotlin.code.style=official

# 构建性能监控
org.gradle.console=verbose

在自定义插件中实现构建优化:

class BuildOptimizationPlugin : Plugin<Project> {
    override fun apply(project: Project) = with(project) {
        // 配置增量构建
        tasks.withType<JavaCompile>().configureEach {
            options.isIncremental = true
        }
        
        // 配置并行编译
        tasks.withType<KotlinCompile>().configureEach {
            kotlinOptions {
                jvmTarget = "11"
                freeCompilerArgs = freeCompilerArgs + listOf(
                    "-Xopt-in=kotlin.RequiresOptIn",
                    "-Xjvm-default=all",
                    "-Xskip-prerelease-check"
                )
            }
        }
        
        // 配置R8优化
        extensions.configure<ApplicationExtension> {
            buildTypes {
                getByName("release") {
                    isCrunchPngs = true
                    isShrinkResources = true
                    isMinifyEnabled = true
                }
            }
        }
        
        // 配置资源优化
        afterEvaluate {
            android?.run {
                packagingOptions {
                    resources {
                        excludes += setOf(
                            "META-INF/*.kotlin_module",
                            "META-INF/*.version",
                            "META-INF/proguard/*",
                            "META-INF/licenses/*",
                            "**/DebugProbesKt.bin",
                            "**/*.proto"
                        )
                        pickFirsts += setOf(
                            "**/libc++_shared.so",
                            "**/libfbjni.so"
                        )
                    }
                }
            }
        }
    }
}

5.3 测试配置优化

为多模块项目配置统一的测试策略:

android {
    testOptions {
        unitTests {
            isIncludeAndroidResources = true
            isReturnDefaultValues = true
            
            all {
                it.jvmArgs("-noverify", "-XX:+UseParallelGC")
                it.minHeapSize = "128m"
                it.maxHeapSize = "512m"
                it.forkEvery = 100
            }
        }
        
        execution = "ANDROIDX_TEST_ORCHESTRATOR"
        
        animationsDisabled = true
    }
}

// 配置模块特定测试任务
tasks.register<Test>("unitTest") {
    group = "verification"
    description = "Runs all unit tests in all modules"
    
    dependsOn(gradle.includedBuilds.flatMap { 
        it.task(":test") 
    })
}

tasks.register<Test>("androidTest") {
    group = "verification"
    description = "Runs all Android tests in all modules"
    
    dependsOn(gradle.includedBuilds.flatMap { 
        it.task(":connectedAndroidTest") 
    })
}

6. 依赖管理高级技巧

6.1 依赖约束和排除

使用依赖约束确保一致的依赖版本:

dependencies {
    // 添加依赖约束
    constraints {
        implementation("com.google.guava:guava") {
            version { strictly("32.1.2-jre") }
            because("Security fix in later versions")
        }
        
        implementation("com.squareup.okhttp3:okhttp") {
            version { require("4.11.0") }
            because("API compatibility with our codebase")
        }
    }
    
    // 排除传递性依赖
    implementation("com.example:library:1.0") {
        exclude(group = "com.unwanted", module = "library")
        exclude(module = "another-unwanted")
    }
    
    // 强制使用特定版本
    configurations.all {
        resolutionStrategy {
            force(
                "androidx.core:core-ktx:1.10.1",
                "org.jetbrains.kotlin:kotlin-stdlib:1.8.20"
            )
            
            // 依赖替换
            substitute(module("com.old:library"))
                .using(module("com.new:library:2.0"))
                .because("The old library was deprecated")
            
            // 缓存配置
            cacheDynamicVersionsFor(10, TimeUnit.MINUTES)
            cacheChangingModulesFor(4, TimeUnit.HOURS)
        }
    }
}

6.2 使用平台(BOM)管理依赖

利用BOM(Bill of Materials)确保依赖兼容性:

dependencies {
    // 导入Compose BOM
    implementation(platform(libs.androidx.compose.bom))
    
    // 不需要指定版本,版本由BOM管理
    implementation(libs.androidx.compose.ui)
    implementation(libs.androidx.compose.ui.tooling)
    implementation(libs.androidx.compose.material3)
    
    // Firebase BOM
    implementation(platform("com.google.firebase:firebase-bom:32.2.2"))
    implementation("com.google.firebase:firebase-analytics")
    implementation("com.google.firebase:firebase-crashlytics")
}

7. 持续集成与部署配置

为多模块项目配置CI/CD流水线:

// 创建CI专用配置文件
// ci.gradle.kts
tasks.register("ciBuild") {
    group = "CI"
    description = "Runs all checks required for CI"
    
    dependsOn(
        ":app:assembleRelease",
        ":app:lintRelease",
        ":test",
        ":androidTest",
        ":dependencyCheck"
    )
}

tasks.register("dependencyCheck") {
    group = "CI"
    description = "Checks for outdated dependencies"
    
    doLast {
        exec {
            commandLine("./gradlew", "dependencyUpdates", "-Drevision=release")
        }
    }
}

// 配置签名信息
signingConfigs {
    create("ciSigning") {
        storeFile = file(System.getenv("KEYSTORE_PATH") ?: "debug.keystore")
        storePassword = System.getenv("KEYSTORE_PASSWORD") ?: "android"
        keyAlias = System.getenv("KEY_ALIAS") ?: "androiddebugkey"
        keyPassword = System.getenv("KEY_PASSWORD") ?: "android"
    }
}

// 配置构建缓存
buildCache {
    local {
        directory = File(rootDir, "build-cache")
        removeUnusedEntriesAfterDays = 7
    }
    
    remote<HttpBuildCache> {
        url = uri("https://ci.example.com/cache/")
        credentials {
            username = System.getenv("CACHE_USER")
            password = System.getenv("CACHE_PASSWORD")
        }
        push = System.getenv("CI") == "true"
    }
}

8. 监控与分析构建性能

实施构建性能监控:

// 构建分析插件
class BuildAnalysisPlugin : Plugin<Project> {
    override fun apply(project: Project) = with(project) {
        // 注册构建扫描任务
        tasks.register("analyzeBuild") {
            group = "verification"
            description = "Analyzes build performance and generates report"
            
            doLast {
                exec {
                    commandLine("./gradlew", "build", "--scan", "--no-daemon")
                }
            }
        }
        
        // 配置构建监听
        gradle.buildFinished {
            val buildDuration = it.result?.endTime?.minus(it.result?.startTime ?: 0) ?: 0
            println("Build completed in ${buildDuration}ms")
            
            if (buildDuration > 120000) { // 2分钟
                logger.warn("Build time exceeds threshold. Consider optimizing your build configuration.")
            }
        }
        
        // 任务时间监控
        tasks.configureEach {
            doFirst {
                logger.lifecycle("Starting task: ${this.name}")
            }
            
            doLast {
                logger.lifecycle("Completed task: ${this.name}")
            }
        }
    }
}

// 配置Gradle企业版进行高级分析
// settings.gradle.kts
plugins {
    id("com.gradle.enterprise").version("3.12.6")
}

gradleEnterprise {
    buildScan {
        termsOfServiceUrl = "https://gradle.com/terms-of-service"
        termsOfServiceAgree = "yes"
        
        publishAlways()
        uploadInBackground = !System.getenv("CI").toBoolean()
        
        background {
            customValue("CI", System.getenv("CI") ?: "false")
            customValue("OS", System.getProperty("os.name"))
            customValue("Java Version", System.getProperty("java.version"))
        }
    }
}

9. 团队协作与知识共享

促进团队协作和知识共享的策略:

9.1 统一的代码风格配置

// 配置Detekt静态代码分析
plugins {
    id("io.gitlab.arturbosch.detekt").version("1.23.0")
}

detekt {
    toolVersion = "1.23.0"
    config = files("$rootDir/config/detekt/detekt.yml")
    buildUponDefaultConfig = true
    
    autoCorrect = true
}

tasks.withType<io.gitlab.arturbosch.detekt.Detekt>().configureEach {
    reports {
        html.required.set(true)
        xml.required.set(true)
        txt.required.set(true)
    }
}

// 配置Spotless代码格式化
plugins {
    id("com.diffplug.spotless").version("6.19.0")
}

spotless {
    kotlin {
        target("**/*.kt")
        ktlint("0.48.2")
        licenseHeaderFile("$rootDir/config/license-header.txt")
    }
    
    kotlinGradle {
        target("**/*.gradle.kts")
        ktlint("0.48.2")
    }
}

9.2 文档和知识共享

创建全面的构建系统文档:

// 创建文档生成任务
tasks.register("generateBuildDocs") {
    group = "documentation"
    description = "Generates documentation for the build system"
    
    doLast {
        val docsDir = file("$rootDir/docs/build-system")
        docsDir.mkdirs()
        
        // 生成模块依赖图
        exec {
            commandLine("./gradlew", ":app:dependencies", "--configuration", "releaseRuntimeClasspath")
        }
        
        // 生成任务文档
        file("$docsDir/tasks.md").writeText("# Build Tasks\n\n")
        tasks.forEach { task ->
            file("$docsDir/tasks.md").appendText("## ${task.name}\n\n")
            file("$docsDir/tasks.md").appendText("**Group**: ${task.group}\n\n")
            file("$docsDir/tasks.md").appendText("**Description**: ${task.description}\n\n")
        }
    }
}

// 配置预提交钩子
tasks.register("installGitHooks") {
    group = "development"
    description = "Installs Git hooks for code quality checks"
    
    doLast {
        val hooksDir = rootProject.file(".git/hooks")
        val preCommitHook = File(hooksDir, "pre-commit")
        
        preCommitHook.writeText("""
            #!/bin/bash
            ./gradlew spotlessCheck detekt
            if [ \$? -ne 0 ]; then
                echo "Code quality checks failed. Please fix the issues before committing."
                exit 1
            fi
        """.trimIndent())
        
        preCommitHook.setExecutable(true)
    }
}

总结

创建可维护的多模块Android项目Gradle脚本需要综合考虑架构设计、工具选择和团队协作多个方面。通过实施本文介绍的最佳实践,您可以构建出高效、稳定且易于维护的构建系统:

  1. 采用模块化架构:通过清晰的模块边界和职责分离提高可维护性
  2. 使用Kotlin DSL:利用类型安全和IDE支持提升脚本质量和开发体验
  3. 实现自定义插件:集中化构建逻辑,减少重复代码
  4. 统一依赖管理:通过版本目录和BOM确保依赖一致性
  5. 优化构建性能:实施缓存、并行执行和增量构建减少构建时间
  6. 建立质量保障:通过静态分析和代码格式化保持代码质量
  7. 促进团队协作:通过文档和标准化配置支持团队协作
最后更新: 2025/9/23 09:31