Skip to content

项目结构与生命周期

源:Gradle 官方文档 - Build Lifecycle | Organizing Gradle Projects

理解 Gradle 项目的目录结构和构建生命周期是掌握 Gradle 的基础,这决定了你如何组织代码和优化构建性能。

Gradle 项目目录结构

单模块项目结构

my-app/
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle.kts
├── build.gradle.kts
├── gradle.properties
└── src/
    ├── main/
    │   ├── java/
    │   └── resources/
    └── test/
        ├── java/
        └── resources/

核心文件说明

gradlew / gradlew.bat

  • Gradle Wrapper 脚本,确保项目使用统一的 Gradle 版本
  • 无需事先安装 Gradle,克隆项目即可构建
  • 首次运行会自动下载指定版本的 Gradle

gradle/wrapper/

  • gradle-wrapper.jar:Wrapper 执行器
  • gradle-wrapper.properties:定义 Gradle 版本
properties
# gradle-wrapper.properties
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip

settings.gradle.kts

  • 项目初始化配置文件
  • 定义项目名称和包含的模块
  • 配置插件仓库和依赖仓库

build.gradle.kts

  • 项目构建脚本
  • 定义插件、依赖和任务

gradle.properties

  • JVM 参数和 Gradle 属性配置
  • 项目全局属性定义

Android 单模块项目结构

my-android-app/
├── gradle/
│   ├── wrapper/
│   └── libs.versions.toml
├── gradlew
├── gradlew.bat
├── settings.gradle.kts
├── build.gradle.kts
├── gradle.properties
└── app/
    ├── build.gradle.kts
    ├── proguard-rules.pro
    └── src/
        ├── main/
        │   ├── java/
        │   ├── kotlin/
        │   ├── res/
        │   └── AndroidManifest.xml
        ├── test/
        │   └── java/
        └── androidTest/
            └── java/

Android 特有目录

gradle/libs.versions.toml

  • 版本目录(Version Catalog)
  • 集中管理依赖版本

app/proguard-rules.pro

  • ProGuard/R8 混淆规则

app/src/main/res/

  • Android 资源文件(layout、drawable、values等)

app/src/main/AndroidManifest.xml

  • Andro应用清单文件

app/src/androidTest/

  • Android 插桩测试(运行在设备上)

多模块项目结构

my-project/
├── gradle/
├── settings.gradle.kts
├── build.gradle.kts
├── gradle.properties
├── app/
│   ├── build.gradle.kts
│   └── src/
├── core/
│   ├── build.gradle.kts
│   └── src/
├── feature-login/
│   ├── build.gradle.kts
│   └── src/
└── buildSrc/
    ├── build.gradle.kts
    └── src/main/kotlin/

settings.gradle.kts 配置:

kotlin
rootProject.name = "my-project"

include(":app")
include(":core")
include(":feature-login")

buildSrc 目录 约定插件

buildSrc 是 Gradle 识别的特殊目录,用于存放可复用的构建逻辑。

buildSrc/
├── build.gradle.kts
└── src/main/kotlin/
    ├── AndroidLibraryConventionPlugin.kt
    └── Versions.kt

buildSrc/build.gradle.kts

kotlin
plugins {
    `kotlin-dsl`
}

repositories {
    google()
    mavenCentral()
}

dependencies {
    implementation("com.android.tools.build:gradle:8.7.3")
    implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:2.1.0")
}

优势

  • 构建逻辑自动对所有模块可见
  • 支持 IDE 自动补全
  • 构建脚本可使用类型安全的 API

使用示例

kotlin
// app/build.gradle.kts
plugins {
    id("android-library-convention")  // buildSrc 中定义的插件
}

构建生命周期

Gradle 构建分为三个阶段,理解它们对优化性能至关重要。

Initialization 阶段

目标:确定哪些项目参与构建。

执行过程

  • 执行 settings.gradle.kts
  • 创建 Settings 对象
  • 评估 include() 声明
  • 为每个项目创建 Project 实例

示例

kotlin
// settings.gradle.kts
println("Initialization: 确定项目结构")

rootProject.name = "my-app"
include(":app")
include(":core")

输出时机:无论运行任何任务,这段代码都会执行。

Configuration 阶段

目标:执行所有项目的构建脚本,配置任务。

执行过程

  • 执行每个 build.gradle.kts
  • 创建和配置任务对象
  • 构建任务依赖图

注意事项 性能陷阱

错误做法

kotlin
// build.gradle.kts
tasks.register("myTask") {
    // 这里的代码在配置阶段执行!
    val result = URL("https://api.example.com").readText()  // 每次都会执行
    
    doLast {
        println(result)
    }
}

正确做法

kotlin
tasks.register("myTask") {
    doLast {
        // 仅在执行阶段运行
        val result = URL("https://api.example.com").readText()
        println(result)
    }
}

配置阶段耗时操作的后果

  • IDE 同步项目卡顿
  • 运行任何任务都会触发该操作
  • 无法充分利用构建缓存

Execution 阶段

目标:执行选定的任务。

执行过程

  • 根据任务依赖关系排序
  • 按顺序执行任务的 action
  • 使用增量构建和缓存优化

任务执行顺序

kotlin
tasks.register("taskA") {
    doLast {
        println("Task A")
    }
}

tasks.register("taskB") {
    dependsOn("taskA")
    doLast {
        println("Task B")
    }
}

运行 ./gradlew taskB

> Task :taskA
Task A
> Task :taskB
Task B

生命周期钩子

Gradle 生命周期 API

监听构建开始

kotlin
gradle.buildStarted {
    println("Build started")
}

监听项目配置完成

kotlin
gradle.afterProject { project ->
    println("${project.name} configured")
}

监听任务图构建完成

kotlin
gradle.taskGraph.whenReady { graph ->
    println("Task graph ready with ${graph.allTasks.size} tasks")
}

监听构建完成

kotlin
gradle.buildFinished { result ->
    if (result.failure != null) {
        println("Build failed: ${result.failure}")
    } else {
        println("Build succeeded")
    }
}

项目生命周期钩子

afterEvaluate 谨慎使用

kotlin
// build.gradle.kts
afterEvaluate {
    // 在当前项目配置完成后执行
    println("Project ${project.name} evaluated")
}

注意:过度使用 afterEvaluate 会导致构建逻辑难以理解和维护。优先使用 Lazy API。


Init Scripts 初始化脚本

Init Scripts 在所有项目之前执行,用于全局配置。

位置

用户主目录

~/.gradle/init.gradle.kts  (macOS/Linux)
C:\Users\<username>\.gradle\init.gradle.kts  (Windows)

Gradle 安装目录

$GRADLE_HOME/init.d/

命令行指定

bash
gradle --init-script custom-init.gradle.kts build

使用场景

全局镜像配置

kotlin
// ~/.gradle/init.gradle.kts
allprojects {
    repositories {
        maven { url = uri("https://maven.aliyun.com/repository/public") }
        google()
        mavenCentral()
    }
}

企业认证配置

kotlin
allprojects {
    repositories {
        maven {
            url = uri("https://repo.company.com/maven")
            credentials {
                username = System.getenv("REPO_USERNAME")
                password = System.getenv("REPO_PASSWORD")
            }
        }
    }
}

自动启用构建扫描

kotlin
initscript {
    repositories {
        gradlePluginPortal()
    }
    dependencies {
        classpath("com.gradle:gradle-enterprise-gradle-plugin:3.16.1")
    }
}

apply<com.gradle.enterprise.gradleplugin.GradleEnterprisePlugin>()

gradleEnterprise {
    buildScan {
        termsOfServiceUrl = "https://gradle.com/terms-of-service"
        termsOfServiceAgree = "yes"
        publishAlways()
    }
}

Project 对象

每个 build.gradle.kts 都关联一个 Project 对象。

常用属性

kotlin
// 项目名称
println(project.name)

// 项目目录
println(project.projectDir)

// 根项目
println(project.rootProject.name)

// 父项目
println(project.parent?.name)

// 子项目
project.subprojects.forEach {
    println(it.name)
}

跨项目配置

配置所有项目

kotlin
// 根 build.gradle.kts
allprojects {
    group = "com.example"
    version = "1.0.0"
}

配置子项目

kotlin
subprojects {
    apply(plugin = "java")
    
    dependencies {
        testImplementation("junit:junit:4.13.2")
    }
}

配置特定项目

kotlin
// 根 build.gradle.kts
project(":app") {
    dependencies {
        implementation(project(":core"))
    }
}

Settings 对象

settings.gradle.kts 中可访问 Settings 对象。

基础配置

kotlin
rootProject.name = "my-app"

// 包含子项目
include(":app")
include(":core")

// 设置项目目录
project(":app").projectDir = file("android-app")

插件管理

kotlin
pluginManagement {
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
    
    plugins {
        id("com.android.application") version "8.7.3"
        kotlin("android") version "2.1.0"
    }
}

依赖解析管理

kotlin
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    
    repositories {
        google()
        mavenCentral()
    }
    
    versionCatalogs {
        create("libs") {
            from(files("gradle/libs.versions.toml"))
        }
    }
}

最佳实践

使用 Gradle Wrapper

  • 确保团队使用统一 Gradle 版本
  • 提交 Wrapper 文件到版本控制

合理组织多模块

  • 按功能拆分模块,不是按层次
  • 避免循环依赖
  • 控制模块粒度

避免配置阶段耗时操作

  • 使用 doLast {} 延迟执行
  • 使用 Lazy API
  • 使用 Provider API

使用 buildSrc

  • 提取可复用的构建逻辑
  • 创建约定插件
  • 定义常量和工具函数

Init Scripts 用途

  • 全局镜像配置
  • 企业认证设置
  • 不要用于项目特定配置

理解生命周期

  • Initialization:确定项目结构
  • Configuration:配置任务
  • Execution:执行任务
  • 90% 的性能问题源于配置阶段