项目结构与生命周期
源: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 版本
# gradle-wrapper.properties
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zipsettings.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 配置:
rootProject.name = "my-project"
include(":app")
include(":core")
include(":feature-login")buildSrc 目录 约定插件
buildSrc 是 Gradle 识别的特殊目录,用于存放可复用的构建逻辑。
buildSrc/
├── build.gradle.kts
└── src/main/kotlin/
├── AndroidLibraryConventionPlugin.kt
└── Versions.ktbuildSrc/build.gradle.kts:
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
使用示例:
// app/build.gradle.kts
plugins {
id("android-library-convention") // buildSrc 中定义的插件
}构建生命周期
Gradle 构建分为三个阶段,理解它们对优化性能至关重要。
Initialization 阶段
目标:确定哪些项目参与构建。
执行过程:
- 执行
settings.gradle.kts - 创建
Settings对象 - 评估
include()声明 - 为每个项目创建
Project实例
示例:
// settings.gradle.kts
println("Initialization: 确定项目结构")
rootProject.name = "my-app"
include(":app")
include(":core")输出时机:无论运行任何任务,这段代码都会执行。
Configuration 阶段
目标:执行所有项目的构建脚本,配置任务。
执行过程:
- 执行每个
build.gradle.kts - 创建和配置任务对象
- 构建任务依赖图
注意事项 性能陷阱:
❌ 错误做法:
// build.gradle.kts
tasks.register("myTask") {
// 这里的代码在配置阶段执行!
val result = URL("https://api.example.com").readText() // 每次都会执行
doLast {
println(result)
}
}✅ 正确做法:
tasks.register("myTask") {
doLast {
// 仅在执行阶段运行
val result = URL("https://api.example.com").readText()
println(result)
}
}配置阶段耗时操作的后果:
- IDE 同步项目卡顿
- 运行任何任务都会触发该操作
- 无法充分利用构建缓存
Execution 阶段
目标:执行选定的任务。
执行过程:
- 根据任务依赖关系排序
- 按顺序执行任务的 action
- 使用增量构建和缓存优化
任务执行顺序:
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
监听构建开始:
gradle.buildStarted {
println("Build started")
}监听项目配置完成:
gradle.afterProject { project ->
println("${project.name} configured")
}监听任务图构建完成:
gradle.taskGraph.whenReady { graph ->
println("Task graph ready with ${graph.allTasks.size} tasks")
}监听构建完成:
gradle.buildFinished { result ->
if (result.failure != null) {
println("Build failed: ${result.failure}")
} else {
println("Build succeeded")
}
}项目生命周期钩子
afterEvaluate 谨慎使用:
// 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/命令行指定:
gradle --init-script custom-init.gradle.kts build使用场景
全局镜像配置:
// ~/.gradle/init.gradle.kts
allprojects {
repositories {
maven { url = uri("https://maven.aliyun.com/repository/public") }
google()
mavenCentral()
}
}企业认证配置:
allprojects {
repositories {
maven {
url = uri("https://repo.company.com/maven")
credentials {
username = System.getenv("REPO_USERNAME")
password = System.getenv("REPO_PASSWORD")
}
}
}
}自动启用构建扫描:
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 对象。
常用属性
// 项目名称
println(project.name)
// 项目目录
println(project.projectDir)
// 根项目
println(project.rootProject.name)
// 父项目
println(project.parent?.name)
// 子项目
project.subprojects.forEach {
println(it.name)
}跨项目配置
配置所有项目:
// 根 build.gradle.kts
allprojects {
group = "com.example"
version = "1.0.0"
}配置子项目:
subprojects {
apply(plugin = "java")
dependencies {
testImplementation("junit:junit:4.13.2")
}
}配置特定项目:
// 根 build.gradle.kts
project(":app") {
dependencies {
implementation(project(":core"))
}
}Settings 对象
settings.gradle.kts 中可访问 Settings 对象。
基础配置
rootProject.name = "my-app"
// 包含子项目
include(":app")
include(":core")
// 设置项目目录
project(":app").projectDir = file("android-app")插件管理
pluginManagement {
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
plugins {
id("com.android.application") version "8.7.3"
kotlin("android") version "2.1.0"
}
}依赖解析管理
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% 的性能问题源于配置阶段