本文作者
作者:yechaoa
链接:
https://juejin.cn/post/7406147963876278312
本文由作者授权发布。
版本管理(Version Management)是指在开发过程中对项目依赖的各个库、框架、插件等版本进行管理和控制。这个过程确保项目中的所有组件以正确的版本组合在一起运行,以避免兼容性问题、漏洞和其他潜在问题。
新建项目时,在app > build.gradle文件中会有一些官方默认的组件依赖,会在dependencies{ }中声明并直接制定具体的版本号。
dependencies {
implementation("androidx.core:core-ktx:1.9.0")
implementation("androidx.appcompat:appcompat:1.6.1")
// ...
}
这里core-ktx依赖的版本号就是一个具体的版本号1.9.0。
这种方式简单直观,但随着项目的依赖变多时,版本管理分散,升级版本也会比较繁琐,维护成本较高,所以适用于依赖少且变化不频繁的项目。
顾名思义,不直接定义具体的版本号,而是通过占位符的方式来代替。
3.1、直接定义
dependencies {
val room_version = "2.6.1"
implementation("androidx.room:room-runtime:$room_version")
annotationProcessor("androidx.room:room-compiler:$room_version")
// To use Kotlin annotation processing tool (kapt)
kapt("androidx.room:room-compiler:$room_version")
// To use Kotlin Symbol Processing (KSP)
ksp("androidx.room:room-compiler:$room_version")
// optional - Kotlin Extensions and Coroutines support for Room
implementation("androidx.room:room-ktx:$room_version")
// optional - RxJava2 support for Room
implementation("androidx.room:room-rxjava2:$room_version")
// optional - RxJava3 support for Room
implementation("androidx.room:room-rxjava3:$room_version")
// optional - Guava support for Room, including Optional and ListenableFuture
implementation("androidx.room:room-guava:$room_version")
// optional - Test helpers
testImplementation("androidx.room:room-testing:$room_version")
// optional - Paging 3 Integration
implementation("androidx.room:room-paging:$room_version")
}
这个示例来自于Android Jetpack中的 room 组件库,从依赖声明来看,必选项不止一个,这种情况就可以把版本号抽出来统一管理,即val room_version = "2.6.1"。
3.2、ext
extra.apply {
set("core-ktx", "1.9.0")
set("appcompat", "1.6.1")
}
在app > build.gradle文件中读取:
dependencies {
implementation("androidx.core:core-ktx:${rootProject.extra.get("core-ktx")}")
implementation("androidx.appcompat:appcompat:${rootProject.extra.get("appcompat")}")
}
除了依赖的版本号,Android中的一些配置信息也可以使用ext来进行统一管理。
extra.apply {
set("applicationId", "com.yechaoa.gradlex")
set("minSdk", 23)
set("targetSdk", 33)
set("core-ktx", "1.9.0")
set("appcompat", "1.6.1")
}
使用:
android {
defaultConfig {
applicationId = rootProject.extra.get("applicationId") as String
minSdk = rootProject.extra.get("minSdk") as Int
targetSdk = rootProject.extra.get("targetSdk") as Int
// ...
}
}
3.3、gradle.properties
# 版本管理示例
applicationId=com.yechaoa.gradlex
minSdk=23
targetSdk=33
core_ktx="1.9.0"
appcompat="1.6.1"
使用:
android {
defaultConfig {
applicationId = properties["applicationId"].toString()
minSdk = properties["minSdk"].toString().toInt()
targetSdk = properties["targetSdk"].toString().toInt()
// ...
}
dependencies {
implementation("androidx.core:core-ktx:${properties["core_ktx"]}")
implementation("androidx.appcompat:appcompat:${properties["appcompat"]}")
}
}
properties["minSdk"]获取的值是Any对象,需要转为所需要的数据结构。
3.4、小结
单论版本管理来讲,这二者差别不大,怎么选择就看自己的使用习惯。
4.1、新建buildSrc文件夹
4.2、新建构建脚本
plugins{
kotlin("jvm") version "1.7.20"
}
repositories {
google()
mavenCentral()
}
dependencies {
implementation(kotlin("stdlib"))
}
自己按需添加。
4.3、编写版本管理代码
object Versions {
const val core_ktx = "1.9.0"
const val appcompat = "1.6.1"
}
4.4、使用
dependencies {
implementation("androidx.core:core-ktx:${Versions.core_ktx}")
implementation("androidx.appcompat:appcompat:${Versions.appcompat}")
}
4.5、进阶
object Libs {
const val core_ktx = "androidx.core:core-ktx:${Versions.core_ktx}"
const val appcompat = "androidx.appcompat:appcompat:${Versions.appcompat}"
}
依赖中的版本号使用Versions.kt文件中定义的版本号。
dependencies {
implementation(Libs.core_ktx)
implementation(Libs.appcompat)
}
4.6、小结
使用buildSrc进行版本管理,依赖和版本集中在一个模块,结构清晰,提升了代码的可读性和维护性,支持代码提示和跳转,使得开发体验也大大提升,适用于多模块或大型项目,对于小型项目来说可能显得复杂了一些。
Version Catalogs全称是version catalog libs,中文是「版本目录」的意思,是Gradle 7.0引入的一项新特性,允许你在一个集中式文件中管理所有依赖版本和插件版本。
5.1、创建版本目录文件
[versions]
[libraries]
[plugins]
versions:定义用于保存依赖项和插件版本的变量。可以在libraries和plugins中使用这些变量。
libraries:定义依赖项。 plugins:定义插件。
5.2、定义依赖项和插件
[versions]
agp = "8.1.1"
ktx = "1.9.0"
appcompat = "1.6.1"
[libraries]
androidx-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "ktx" }
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
5.3、修改依赖项和插件
dependencies {
implementation(libs.androidx.ktx)
implementation(libs.androidx.appcompat)
}
@Suppress("DSL_SCOPE_VIOLATION")
plugins {
alias(libs.plugins.android.application) apply false
// ...
}
如果使用的是低于 8.1 的 Gradle 版本,则需要在使用版本目录时为 plugins{} 代码块添加注解 (@Suppress("DSL_SCOPE_VIOLATION")),原因是Gradle没做Kotlin DSL的扩展适配。
plugins {
alias(libs.plugins.android.application)
// ...
}
5.4、小结
version catalogs对于中小型项目来说更友好一些,配置简单,标准化且易读,易于维护。
除了上面介绍的几种依赖版本管理方式之外,还有一些其他方式,介绍两个。
6.1、动态添加
class DynamicDependencyPlugin : Plugin<Project> {
override fun apply(target: Project) {
target.afterEvaluate {
if (target.hasProperty("dynamicEnable")) {
target.configurations.all {
dependencies.add("implementation", "com.yechaoa.plugin:library:1.0.0")
}
}
}
}
}
configurations.configureEach {
resolutionStrategy.eachDependency {
val details = this as DependencyResolveDetails
val requested = details.requested
if (requested.group == "com.squareup.okhttp3" && requested.name == "okhttp") {
details.useVersion("4.10.0")
}
// ...
}
}
通过上述几种版本管理方式,你可以根据项目规模、团队协作方式等,来选择适合的依赖版本管理策略,不用局限于某一种,也可以组合来使用。
GitHub
相关文档
ExtraPropertiesExtension
https://docs.gradle.org/current/dsl/org.gradle.api.plugins.ExtraPropertiesExtension.html
Sharing Build Logic between Subprojects
https://docs.gradle.org/current/userguide/sharing_build_logic_between_subprojects.html#sec:using_buildsrc
Use buildSrc to abstract imperative logic
https://docs.gradle.org/current/userguide/organizing_gradle_projects.html#sec:build_sources
Sharing dependency versions between projects
https://docs.gradle.org/current/userguide/platforms.html
Declaring Rich Versions
https://docs.gradle.org/current/userguide/rich_versions.html#rich-version-constraints
TOML document
https://toml.io/en/
将 build 迁移到版本目录
https://developer.android.google.cn/build/migrate-to-catalogs?hl=zh-cn
【Gradle-6】一文搞懂Gradle的依赖管理和版本决议
https://juejin.cn/post/7215579793261117501