Gradle 和 Maven 在多模块项目管理上确实有一些区别,但它们的核心思想是相似的。在 Android 项目中,根目录的build.gradle文件和每个模块内的build.gradle文件扮演着不同的角色。

Android项目中build.gradle文件的分工

在 Android 项目里,一般有两类build.gradle文件:

1. 根目录的build.gradle** (Top-level build file)**

这个文件主要用于定义整个项目的全局配置,它相当于项目的“总指挥”。

plugins {
    alias(libs.plugins.android.application) apply false
    alias(libs.plugins.kotlin.android) apply false
    id 'com.google.dagger.hilt.android' version '2.57' apply false
}

主要职责:

  • 定义插件版本: 根目录的build.gradle文件中通常使用plugins { ... }块来声明整个项目需要使用的插件及其版本号。这些插件本身可能不直接应用到所有模块,但它们会作为“库”被模块引用。例如:
    • alias(libs.plugins.android.application) apply false
    • id 'com.google.dagger.hilt.android' version '2.57' apply false

这里的apply false非常重要,它表示该插件只被声明,但不会立即应用。它仅仅是告诉Gradle,这个项目可以“使用”这些插件,而具体的应用工作交给各个模块自己决定。

  • 集中管理依赖: 在一些更现代的Gradle配置中,你可能会看到根目录的build.gradlesettings.gradle文件与版本目录(Version Catalogs)结合使用,来集中管理所有依赖的版本,避免在不同模块中重复声明。

特点:

  • **作用对象:**整个项目,包括所有模块(module)。
  • 定义全局版本号 / 依赖 / 插件,供子模块使用。
  • 类似 Maven 的 parent pom,但不是直接“继承”,更像“声明共享的配置和插件版本”。

举例:Hilt 插件在根目录声明了版本 2.57,子模块只需要写 id("com.google.dagger.hilt.android"),就会用这个版本号。

2. 模块内的build.gradle** (Module-level build file)**

这个文件是每个模块自己的“配置文件”,它定义了该模块的具体行为。

plugins {
    id("com.android.library")
    alias(libs.kotlin.android)
    id("kotlin-kapt")
    id("com.google.dagger.hilt.android")
}
 
android {
    namespace 'com.example.applistener_bestpractices'
    compileSdk 35
    ...
        }
 
dependencies {
    implementation libs.androidx.core.ktx
    implementation libs.androidx.appcompat
    ...
        implementation "com.google.dagger:hilt-android:2.57"
    kapt "com.google.dagger:hilt-compiler:2.57"
}

主要职责:

  • 应用插件: 模块内的build.gradle会通过plugins { ... }块来真正应用它所需要的插件。这些插件必须在根目录的build.gradle中已经声明过。例如:
    • id("com.android.library")
    • id("com.google.dagger.hilt.android")

当一个模块应用了com.android.library插件,Gradle 就知道这是一个 Android 库模块;当它应用了com.google.dagger.hilt.android插件,Gradle 就会为它启用 Dagger Hilt 的特定功能。

  • 配置模块:android { ... }块中,你将配置该模块独有的信息,例如:
    • namespace(包名)
    • compileSdkminSdk 版本
    • buildTypes(发布和调试配置)
    • compileOptions
  • 声明依赖:dependencies { ... }块中,你将声明该模块所需要的具体依赖库。这些依赖只对当前模块有效,不会自动传递给其他模块,除非你将这个模块作为依赖添加给其他模块

特点:

  • 作用对象:单个模块(可以是 app 模块,也可以是 library 模块)。
  • 配置 Android 编译选项(compileSdk、minSdk、buildTypes 等)。
  • 配置 模块依赖(implementation / api / testImplementation)。
  • 引入插件(如 Hilt、Kotlin)—会自动用根目录声明的版本。

Gradle 与 Maven 的类比和区别

将根目录的build.gradle与 Maven 的父 POM 进行类比是很恰当的,但它们的工作方式有所不同。

  • Maven 的父子关系: Maven 的父 POM(pom.xml)通过<dependencyManagement>来管理所有子模块的依赖版本。一旦在父 POM 中声明了依赖,子模块可以省略版本号来直接继承。这种方式是继承和传递。父 POM 更像一个模板,子模块从中继承配置。
    • 父 POM 引入依赖,子模块自动继承
    • 子模块间的依赖默认不冲突,因为每个模块都有自己的依赖作用域。
  • Gradle 的“应用”关系: Gradle 的根build.gradle不是通过继承,而是通过声明和应用来工作的。根文件只是声明了项目中所有可用的“工具箱”,而每个模块需要自己决定要从这个工具箱里取出哪些工具(插件)和材料(依赖)来使用。
    • build.gradle声明插件和版本,但不自动应用
    • 模块build.gradle根据需要显式应用插件和声明依赖。

这种“声明与应用”的设计让 Gradle 的配置更加灵活和模块化。它避免了 Maven 中一些复杂的继承问题,使每个模块的配置文件都更加清晰和独立。

特性MavenGradle (Android)
父子关系父 POM 可以定义依赖、插件,子模块继承父模块依赖根 build.gradle 可以声明插件版本和全局配置,子模块引用后生效
依赖传递依赖继承(父 pom → 子模块自动继承依赖)默认不自动继承 dependencies,需要在根 build.gradle 用subprojects { dependencies { ... } }才能共享依赖
插件管理在 POM 插件管理中统一版本根 build.gradle 中用plugins { id ... version ... apply false }声明,子模块apply时使用该版本
模块互依赖父模块不影响子模块之间依赖冲突模块依赖冲突需要手动处理,Gradle 有implementation/api/compileOnly区分依赖可见性
灵活性XML,比较固定Groovy / Kotlin DSL,非常灵活,可用条件逻辑、循环、函数封装

根 build.gradle 和模块 build.gradle 的实际关系

可以这样理解:

  1. 插件版本管理
    根 build.gradle 声明 Hilt、Kotlin、Android 插件版本,子模块只要id("...")就会引用根目录声明的版本。
  2. 不自动继承 dependencies
    Gradle 默认 模块间依赖不会自动继承。每个模块的dependencies都是独立的。
    • 如果你想共享依赖,可以在根 build.gradle 写subprojects { dependencies { ... } }或者用 平台(platform)依赖
  3. 配置继承
    根目录可以配置一些全局参数,比如:
subprojects {
    tasks.withType(JavaCompile) {
        sourceCompatibility = JavaVersion.VERSION_21
        targetCompatibility = JavaVersion.VERSION_21
    }
}

这样子模块就统一了编译选项。

总结

根目录的build.gradle文件是项目的全局配置中心,它决定了整个项目有哪些插件和依赖版本可用;而每个模块的build.gradle文件则是该模块的局部配置中心,它决定了该模块如何使用这些可用的工具来构建自己。

💡 提示:

  • 现代 Android 推荐用 版本管理 + plugins alias + libs.versions.toml 来统一依赖版本。
  • 每个模块保持独立的 dependencies,可以减少冲突,但也要主动在根 build.gradle 或 platform 管理公共库版本。

更新: 2025-09-05 09:49:44
原文: https://www.yuque.com/dongpozhouzi-mshe3/zhm85g/hgtcoaa8ofoto306


相关笔记