Version Catalog:统一版本管理的新时代
说实话,在接触 Version Catalog 之前,我管理 Gradle 依赖的方式还挺原始的。就是那种在根项目的 build.gradle 里定义一堆 ext 变量,然后各个模块引用。项目小的时候还好,一旦模块多了,维护起来简直是一场噩梦。
我记得有一次,团队里两个同事同时升级了同一个库的不同版本,结果编译报错查了半天。从那以后,我就下定决心要找一个更靠谱的方案。嗯,Version Catalog 就是那个答案。
什么是 Version Catalog?
说白了,Version Catalog 是 Gradle 7.0 引入的一个特性。它让你用一个统一的 libs.versions.toml 文件来管理所有依赖的版本号、库声明和插件版本。
你想想看,以前我们是怎么做的?
// 老方式:ext 变量
ext {
compose_version = '1.3.0'
retrofit_version = '2.9.0'
okhttp_version = '4.10.0'
}
// 然后在各个模块里引用
implementation "androidx.compose.ui:compose-ui:$compose_version"
implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
这种方式有什么问题?变量名容易冲突,IDE 提示不友好,而且你没法快速看到某个库的所有引用位置。
用 Version Catalog 之后,画风就变了:
// libs.versions.toml
[versions]
compose = "1.3.0"
retrofit = "2.9.0"
[libraries]
compose-ui = { group = "androidx.compose.ui", name = "compose-ui", version.ref = "compose" }
retrofit = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit" }
// 在 build.gradle.kts 里引用
implementation(libs.compose.ui)
implementation(libs.retrofit)
看到区别了吗?类型安全、自动补全、集中管理,这才是现代 Android 项目该有的样子。
libs.versions.toml 文件结构
这个文件通常放在 gradle/ 目录下。我习惯把它拆成三个主要区块:
| 区块 | 作用 | 示例 |
|---|---|---|
| [versions] | 定义版本号变量 | kotlin = "1.8.0" |
| [libraries] | 声明库依赖 | kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" } |
| [plugins] | 声明 Gradle 插件 | kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } |
声明与使用版本目录
先看一个完整的 libs.versions.toml 示例:
[versions]
agp = "8.1.0"
kotlin = "1.8.20"
compose-bom = "2023.05.01"
compose-compiler = "1.4.6"
retrofit = "2.9.0"
okhttp = "4.11.0"
coroutines = "1.7.1"
[libraries]
# BOM
compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" }
compose-ui = { group = "androidx.compose.ui", name = "compose-ui" }
compose-material3 = { group = "androidx.compose.material3", name = "material3" }
# 网络
retrofit-core = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
retrofit-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "retrofit" }
okhttp-core = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }
okhttp-logging = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "okhttp" }
# Kotlin
kotlinx-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "coroutines" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
然后在模块的 build.gradle.kts 里这样用:
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
}
android {
// ...
}
dependencies {
// Compose
implementation(platform(libs.compose.bom))
implementation(libs.compose.ui)
implementation(libs.compose.material3)
// 网络
implementation(libs.retrofit.core)
implementation(libs.retrofit.gson)
implementation(libs.okhttp.core)
implementation(libs.okhttp.logging)
// 协程
implementation(libs.kotlinx.coroutines)
}
libs 扩展对象。库名中的连字符会被转为点号,比如 compose-ui 变成 libs.compose.ui。
多模块统一版本管理
这才是 Version Catalog 真正发光的地方。我参与过一个 20+ 模块的项目,每个模块都有自己的依赖。以前最怕的就是版本不一致,比如 moduleA 用了 Retrofit 2.9.0,moduleB 用了 2.8.0,编译时没问题,运行时却出了诡异 bug。
有了 Version Catalog,所有模块都从同一个地方读取版本:
// 所有模块的 build.gradle.kts 都这样写
dependencies {
implementation(libs.retrofit.core) // 版本统一由 toml 控制
implementation(libs.okhttp.core)
}
想升级 Retrofit?只需要改 toml 文件里的版本号,然后重新编译。所有模块自动同步,不会遗漏。
implementation("com.squareup.retrofit2:retrofit:2.9.0")。这样 Version Catalog 就形同虚设了。所有依赖必须通过 libs 引用。
目录的共享与发布
如果你的公司有多个项目,或者你想把公共依赖库分享给团队,Version Catalog 支持发布到 Maven 仓库。
具体做法是创建一个独立的 Gradle 项目,里面只放 toml 文件,然后发布:
// 在独立的 catalog 项目中
plugins {
`version-catalog`
`maven-publish`
}
catalog {
versionCatalog {
from(files("gradle/libs.versions.toml"))
}
}
publishing {
publications {
create<MavenPublication>("catalog") {
from(components["versionCatalog"])
}
}
}
其他项目引用时,在 settings.gradle.kts 里配置:
dependencyResolutionManagement {
repositories {
mavenCentral()
// 公司私有仓库
maven { url = uri("https://your-company.com/repo") }
}
versionCatalogs {
create("libs") {
from("com.yourcompany:catalog:1.0.0")
}
}
}
这样,所有项目都能共享同一套依赖版本标准。新项目初始化时,只需要引入 catalog 坐标,不用再手动写一堆依赖声明。
知识体系总览
下面这张图帮你理清 Version Catalog 的核心脉络:
最佳实践与避坑指南
- 命名规范要统一:我习惯用
库名-功能的格式,比如retrofit-core、okhttp-logging。这样在 IDE 里输入libs.后,自动补全列表一目了然。 - BOM 要特殊处理:Compose 的 BOM 需要用
platform()包裹,否则版本可能不生效。我见过有人直接implementation(libs.compose.bom),结果版本没对齐,UI 渲染异常。 - 不要混用新旧方式:既然用了 Version Catalog,就彻底放弃
ext变量。混用只会让维护更混乱。 - 定期清理无用依赖:项目迭代过程中,有些库可能不再使用了。记得及时从 toml 文件里移除,保持目录干净。
libs. 后按 Ctrl+Space,可以看到所有可用的库。如果发现某个库没出现,检查一下 toml 文件的语法是否正确。
说实话,Version Catalog 是我近几年在 Gradle 构建中最喜欢的特性之一。它让依赖管理变得清晰、安全、可维护。如果你还在用 ext 变量管理版本,我建议你尽快迁移过来。刚开始可能会有点不习惯,但用上一周后,你就再也回不去了。
公众号:蓝海资料掘金营,微信deep3321