前言
前段时间使用新版本的Android Studio创建了个项目想测试点东西,项目创建后发现整个Gradle的依赖管理发生了巨大的变化。
先说一下我使用的Android Studio的版本如下。
创建项目后主要变化如下:
- 原本的.gradle变成了.gradle.kts,也就是说以后肯定是以kts脚本为主了。kts相较于grovvy使用起来更加方便,语言统一,且有提示。
- AGP版本升到了8+
- 版本依赖变成了下面这个样子
点击依赖发现会跳转到 gradle目录下的libs.versions.toml
文件内
这个libs.version.toml实际上是Gradle新版本提供的一种依赖管理方式,详情可以看 version catalog 官方文档
在version catalog 之前,实际上在Android中的Gradle依赖管理还有以下几种方式
- 直接依赖 最原始的方式,维护依赖版本时很麻烦
- 在ext中声明依赖的信息,然后在依赖处使用ext中声明的变量进行依赖管理,初步解决了依赖版本统一的问题,但写起来没提示,还是很麻烦
- 通过内置的buildSrc插件进行依赖管理,在插件内部通过代码维护依赖信息,使用依赖时导包使用即可,本质上就是个静态变量的方式。这种方式算是比较友好了,写依赖的时候有提示,在编译期会进行校验,由于每次更改都会导致全量编译,因此对编译速度有一定的影响。
- 使用Include build,可以像buildSrc那样把依赖信息维护在代码内,使用时也跟跟buildSrc类似,但是编译速度要更快,也有提示以及点击跳转等功能。
前面几种方式我都用过,在version catalog出来之前的很长一段时间我用的都是Include build这种方式,但是其还有一个问题没法解决就是根目录下的插件版本没办法管理到,如图所示,例如我希望把therouter的插件版本也管理起来,因为他的版本我已经在com.yzq.dependency-manager中声明过了。
但是不管是buildSrc还是Include build,都是编译期才生效,并且其生命周期也都在根目录build.geadle执行之后,所以没办法把插件相关的配置给维护起来。
而 Vesion Catalog 就解决了这个问题。
Vesion Catalog的使用和发布
Version Catalog的使用非常简单,官方文档介绍的已经非常详细了,推荐直接去看 官方文档 即可。
需要注意的是使用Version Catalog对Gradle的版本是有要求的,推荐直接在AGP8以上的版本使用,没有什么奇怪的限制。
这里我门快速过一下使用方式
方式一
直接在settings.gradle.kts中声明versionCatalogs以及相关的配置信息即可
dependencyResolutionManagement {repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)repositories {google()mavenCentral()}versionCatalogs {create("androidLibs") {/*声明版本号*/version("minSdk", "21")version("compileSdk", "33")version("targetSdk", "33")version("kotlin", "1.8.22")/*** 声明依赖库* 方式一:别名, 依赖库的具体坐标和版本* 方式二:别名, group,artifact,version*/library("androidx-appcompat", "androidx.appcompat:appcompat:1.3.1")//方式一library("androidx-core-ktx", "androidx", "core:core-ktx").version("1.6.0")//方式二/*把依赖库打包 一起依赖*/bundle("androidx", listOf("androidx-appcompat", "androidx-core-ktx"))/*声明插件*/plugin("android-library", "com.android.library").version("8.0.2")plugin("kotlin-android", "org.jetbrains.kotlin.android").versionRef("kotlin")}}
}
随后使用方式如下:
plugins {
// id("com.android.library")
// id("org.jetbrains.kotlin.android")/*依赖插件 等同于上面注释掉的代码*/alias(androidLibs.plugins.android.library)alias(androidLibs.plugins.kotlin.android)
}android {namespace = "com.yzq.mylibrary2"compileSdk = androidLibs.versions.compileSdk.get().toInt()
}dependencies {/*单独依赖*/implementation(androidLibs.androidx.core.ktx)implementation(androidLibs.androidx.appcompat)/*打包依赖*/implementation(androidLibs.bundles.androidx)
}
在添加依赖时是有提示的,同时把插件的版本也管理起来了。
方式二
方式二是官方推荐的方式,就是在toml文件中管理依赖。创建新项目时默认就是这种方式,默认的文件路径在文章开头也给出了,是在gradle文件夹里。
至于写法也很简单,这里不赘述了。
- [versions]就是声明版本的
- [libraries]就是声明依赖库的
- [plugins]就是声明插件的
- [bundles]就是打包依赖,用来简化依赖
示例如下:
[versions]
agp = "8.2.0-alpha10"
kotlin = "1.8.21"
core-ktx = "1.9.0"
junit = "4.13.2"
androidx-test-ext-junit = "1.1.5"
espresso-core = "3.5.1"
appcompat = "1.6.1"
material = "1.9.0"
constraintlayout = "2.1.4"
lifecycle-livedata-ktx = "2.6.1"
lifecycle-viewmodel-ktx = "2.6.1"
navigation-fragment-ktx = "2.6.0"
navigation-ui-ktx = "2.6.0"[libraries]
core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "core-ktx" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-test-ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidx-test-ext-junit" }
espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espresso-core" }
appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
lifecycle-livedata-ktx = { group = "androidx.lifecycle", name = "lifecycle-livedata-ktx", version.ref = "lifecycle-livedata-ktx" }
lifecycle-viewmodel-ktx = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "lifecycle-viewmodel-ktx" }
navigation-fragment-ktx = { group = "androidx.navigation", name = "navigation-fragment-ktx", version.ref = "navigation-fragment-ktx" }
navigation-ui-ktx = { group = "androidx.navigation", name = "navigation-ui-ktx", version.ref = "navigation-ui-ktx" }[plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" }
kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }[bundles]
androidX = { modules = ["core-ktx", "appcompat", "material", "constraintlayout", "lifecycle-livedata-ktx", "lifecycle-viewmodel-ktx", "navigation-fragment-ktx", "navigation-ui-ktx"] }
使用上跟方式一完全一样,默认我们不需要在settings.gradle.kts配置任何东西。gradle会自动加载gradle目录下的libs.versions.toml文件,默认的名称也是libs。
当然,如果你想把文件名字或者路径改一下也完全没问题,改完后手动配置下依赖即可。
例如
versionCatalogs {create("libs") {from(files("version-catalog/libs.versions.toml"))}}
发布到远端
如果你没有共享依赖的需求,那么上面的方式已经足够使用了。
但是现在基本上都是组件化开发了,特别是当组件数量比较多或者公司内有其他App时,大概率就会有统一依赖版本以及共享依赖的需求了。
那我们可以把Version Catalog发布到远端,组件或其他项目需要时直接依赖然后使用即可,这样就很方便的实现了版本的统一以及快速依赖了。毕竟拷贝来拷贝去非常麻烦且不好维护。
Version Catalog发布也比较简单,按照 官方文档 来即可。
发布完成后,直接依赖远程的配置就可以了。
示例:
versionCatalogs {create("libs") {from("com.xeonyu:version-catalog:0.0.2-SNAPSHOT")}
}
到这里,我们就实现了共享版本目录了。
配合Include Build 简化配置
解决完共享依赖的问题后,我们还可以配合之前用的Include Build来简化日常的依赖配置。
比如作为一个module,它的配置比较固定,无非就是些 minSdk,targetSdk,混淆配置,插件配置之类的,而且每个module的配置基本一致,同时作为公司内部的组件,我们希望组件的版本(例如minSdk,targetSdk等)能够跟App的版本保持一致,那么我们就可以结合Include Build加上version catalog来实现了。
还有一些三方依赖比如room,therouter等,他们的配置是固定成套的,我们可以通过写插件的方式把他们的配置集中起来,项目需要用到时直接一行代码就能搞定依赖了。
示例:
plugins {alias(libs.plugins.yzq.android.application)alias(libs.plugins.yzq.android.room)
}
插件部分不是很通用,一般需要根据自身需要编码定制,这里就不啰嗦了,主要是提供些思路,抛砖引玉。
关于插件的发布可以参考
发布Gradle插件 文档,剩下的就是写插件发布然后应用了。
总结
总而言之,Version Catalog和Include Build可以帮助开发人员更好地管理和配置项目中的依赖库和插件,提高开发效率,并保持版本的统一性。同时,通过发布Version Catalog和编写Gradle插件,可以实现依赖的共享和集中管理。
如果你觉得本文对你有帮助,麻烦动动手指顶一下,可以帮助到更多的开发者,如果文中有什么错误的地方,还望指正,转载请注明转自喻志强的博客 ,谢谢!