Version Catalog 是 Gradle 8.0 版本中正式发布一个新特性. 用来管理一个或者多个项目中的依赖版本.
优势
官方文档里面提到的 version catalog 方式声明依赖的优点有:
- gradle 会生成 type safe 的访问方式, IDE 可以自动补全.
- 可以统一控制所有的模块的依赖版本.
- 支持
bundle功能, 可以将依赖分组, 统一应用. - 可以单独声明依赖版本, 这样多个依赖可以使用相关的版本号.
现在常见的依赖声明方式是在 buildSrc 里面定义. 比如下面的代码.
object Versions {
const val groovy = "3.0.5"
}
object Libs {
const val groovy_core = "org.codehaus.groovy:groovy:${Versions.groovy}"
}
上述优点中 1, 2, 4 其实 buildSrc 的方式也可以支持. 只有第三点是成立的.
不过 buildSrc 还有一个问题, 就是 buildSrc 项目的更新会导致编译缓存失效. 也就是说只要更新依赖版本就会导致应用全量编译. 使用 version catalog 就可以规避这个问题.
基础使用方式
启用功能并创建一个 catalog
虽然可以直接使用 gradle 提供的 api 来创建和定义 version catalog. 但是还是更推荐使用 toml 格式的配置文件来申明, 可读性更强.
gradle 会默认读取 projectRoot/gradle/libs.versions.toml 文件, 并创建一个名为 libs 的 catalog.
如果 gradle 版本在 8.0 以下, 需要先启用该功能, 在 settings.gradle.kts 中加入下面的代码:
enableFeaturePreview("VERSION_CATALOGS")
libs.versions.toml 可以包含四个部分, 分别是
versions定义一些版本限制libraries定义依赖库的别名bundles定义依赖分组plugins定义插件
添加依赖
在 libs.versions.toml 中输入以下内容:
[libraries]
androidx-core = "androidx.core:core-ktx:1.9.0"
androidx-lifecycle = "androidx.lifecycle:lifecycle-runtime-ktx:2.6.1"
这样就定义了两个依赖库, 依赖名称为 androidx-core 和 androidx-lifecycle
命名规则
依赖的名称中可以包含字母, 数字还有三个特殊符号: -, _ 和 .. Android 官方迁移指南建议使用 - 来分割.
在 settings.gradle.kts 中声明后, 就在模块中使用了. 会将-转换成., 这样就可以用来给依赖分层.
dependencies {
implementation(libs.androidx.core)
implementation(libs.androidx.lifecycle)
}
版本管理
可以在 versions 部分来声明一些公用的版本号, 并在 libraries 中引用. 使用方法如下:
[versions]
lifecycle="2.6.1"
[libraries]
androidx-lifecycle-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycle"}
androidx-lifecycle-viewmodel = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "lifecycle"}
添加插件
插件声明在 plugins部分, 也可以引用 versions 模块的里面的版本号
[versions]
androidGradlePlugin = "8.1.1"
[plugins]
# 引用版本号定义
android-application= { id = "com.android.application", version.ref = "androidGradlePlugin"}
# 直接定义
kotlin-android = "org.jetbrains.kotlin.android:1.8.10"
使用方法如下:
plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.kotlin.android) apply false
}
添加 bundle
bundle 是 version catalog 的 killer feature, 是迁移的最大动力. bundle 是一系列依赖库的集合, 可以一次性地引入多个库. 比如一定一个 android-lifecycle 的 bundle:
[libraries]
androidx-lifecycle-ktx = ...
androidx-lifecycle-compose = ...
androidx-lifecycle-viewmodel = ...
androidx-lifecycle-viewmodel-compose = ...
androidx-lifecycle-livedata = ...
[bundles]
android-lifecycle = [
"androidx-lifecycle-ktx",
"androidx-lifecycle-compose",
"androidx-lifecycle-viewmodel",
"androidx-lifecycle-viewmodel-compose",
"androidx-lifecycle-livedata",
]
只需要一行就能添加所有的依赖
dependencies {
implementation(libs.android.lifecycle)
}
在 Plugin 代码中使用
当前对多个模块的编译脚本管理主要使用 convention plugin, 很遗憾, 在 plugin 代码中不能使用 type-safe 的 API 来引用依赖. 不过还是可以使用原始的 API 来读取里面的配置.
// named 的参数跟 settings.gradle.kts 配置的名称要一致
val libs = extensions.getByType<VersionCatalogsExtension>().named("libs")
// 输出 alias 列表, 确定读取正确
println("libraries: ${libs.libraryAliases}")
dependencies {
// 文档中是 "androidx-core", 但是测试下来应该需要用转换后的名称.
libs.findLibrary("androidx.core").ifPresent {
implementation(it)
}
}
Platform 支持
Gradle 的 platform 特性支持 maven 的 bom(bill of material files) 文件. 有些常用的库是自带 BOM 的, 比如 Android 的 Compose, 就是使用 BOM 来管理相关依赖的版本.
Version Catalog 自然也是支持 BOM 的. 使用方法跟普通的依赖也没有太大的区别, 不过要求必须要使用 long-notation 的形式.
[libraries]
# bom 文件
androidx-compose-bom = "androidx.compose:compose-bom:2023.03.00"
#
# version catalog 使用 short-notation 定义时, 必须同时包含 group, name, version
# 三个部分, 缺一部分就是非法的. 因此使用 bom 文件时不能使用 short-notion 来定义
# 非法格式:
# androidx-compose-ui = "androidx.compose.ui:ui"
#
androidx-compose-ui = { group = "androidx.compose.ui", name="ui"}
使用方法如下:
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.compose.ui)