網(wǎng)站首頁 編程語言 正文
發(fā)展歷史
Gradle?的依賴管理是一個(gè)從開始接觸?Android?開發(fā)就一直伴隨著我們的問題(作者是Android開發(fā),僅以此為例),從最初的?沒有統(tǒng)一管理
?到?通過.gradle或gradle.properties管理,再到?Kotlin?出現(xiàn)之后使用?buildSrc 管理
?以及在這基礎(chǔ)上優(yōu)化的?Composing Builds
,Gradle?依賴管理一直在不斷的發(fā)展、更新,而到了?Gradle 7.0,Gradle?本身又專門提供了全新的?Version Catalogs
?用于依賴管理,今天我們就來說說這些方式的優(yōu)劣及使用方式吧。
最原始的依賴
當(dāng)我們通過?Android Studio?創(chuàng)建一個(gè)新項(xiàng)目,這個(gè)項(xiàng)目里面默認(rèn)的依賴就是最原始的,沒有經(jīng)過統(tǒng)一管理的;如果你的項(xiàng)目中只有一個(gè)?module
,那么這種默認(rèn)的管理方式也是可以接受的,是否對(duì)它進(jìn)行優(yōu)化,這取決于你是否愿意投入成本去修改,談不上什么優(yōu)劣。
使用?.gradle?配置
當(dāng)你的項(xiàng)目中?module
?的數(shù)量超過一個(gè)甚至越來越多的時(shí)候,對(duì)?Gradle?依賴進(jìn)行統(tǒng)一管理就變得重要起來,因?yàn)槟悴粫?huì)想在升級(jí)一個(gè)三方依賴的版本后發(fā)現(xiàn)沖突,然后一個(gè)個(gè)打開各個(gè)?module
?的?build.gradle
?文件,找到你升級(jí)的那個(gè)依賴引用,重復(fù)的進(jìn)行版本修改;
因此我們有了初步的優(yōu)化方案:
- 在項(xiàng)目根目錄下創(chuàng)建?
config.gradle
?文件,在其中按照以下格式添加相關(guān)配置;
ext { android = [ compileSdkVersion: 30 ] dependencies = [ "androidx-core-ktx" : "androidx.core:core-ktx:1.3.2", "androidx-appcompat": "androidx.appcompat:appcompat:1.2.0", "google-material" : "com.google.android.material:material:1.3.0" ] }
- 在項(xiàng)目根目錄下的?
build.gradle
?文件頂部添加?apply from: "config.gradle"
; - 在各個(gè)?
module
?的?build.gradle
?中就可以通過?rootProject
?來引用對(duì)應(yīng)的依賴及參數(shù)了;
... android { compileSdkVersion rootProject.ext.android.compileSdkVersion } ... dependencies { implementation rootProject.ext.dependencies["androidx-core-ktx"] implementation rootProject.ext.dependencies["androidx-appcompat"] implementation rootProject.ext.dependencies["google-material"] } ...
使用這種方式,我們就能夠?qū)㈨?xiàng)目中的版本配置、三方依賴統(tǒng)一管理起來了,但是這種方式還是有缺陷的,我們無法像正常代碼中一樣便捷的跳轉(zhuǎn)到依賴定義的地方,也不能簡(jiǎn)單的找到定義的依賴在哪些地方被使用。
使用?gradle.properties?配置
這個(gè)方式和上面的方式類似,把依賴相關(guān)數(shù)據(jù)定義到?gradle.properties
?文件中:
... androidx-core-ktx = androidx.core:core-ktx:1.3.2 androidx-appcompat = androidx.appcompat:appcompat:1.2.0 androidx-material = com.google.android.material:material:1.3.0
在各個(gè)?module
?的?build.gradle
?中使用;
... dependencies { implementation "${androidx-core-ktx}" implementation "${androidx-appcompat}" implementation "${google-material}" }
這種方式相對(duì)于?.gradle
?方式不需要單獨(dú)創(chuàng)建?config.gradle
?文件,但是同樣的也無法快速定位到定義的地方及快速跳轉(zhuǎn)到依賴使用。
使用?buildSrc?配置
在?Kotlin?的支持下,我們又有了新的方案,這個(gè)方案依賴于?IDEA?會(huì)將?buildSrc
?路徑作為插件編譯到項(xiàng)目以及?Kotlin dsl?的支持,并且解決上面兩個(gè)方案依賴無法快速跳轉(zhuǎn)問題;
使用方式如下:
- 在項(xiàng)目根目錄新建文件夾?
buildSrc
,并在該路徑下新建?build.gradle.kts
?文件,該文件使用?Kotlin?語言配置
repositories { google() mavenCentral() } plugins { // 使用 kotlin-dsl 插件 `kotlin-dsl` }
- 在?
buildSrc
?中添加源碼路徑?src/main/kotlin
,并在源碼路徑下添加依賴配置?Dependencies.kt
object Dependencies { const val ANDROIDX_CORE_KTX = "androidx.core:core-ktx:1.3.2" const val ANDROIDX_APPCOMPAT = "androidx.appcompat:appcompat:1.2.0" const val GOOGLE_MATERIAL = "com.google.android.material:material:1.3.0" }
- 在各個(gè)?
module
?中的?build.gradle.kts
?文件中使用依賴
... dependencies { implementation(Dependencies.ANDROIDX_CORE_KTX) implementation(Dependencies.ANDROIDX_APPCOMPAT) implementation(Dependencies.GOOGLE_MATERIAL) }
這個(gè)方案的優(yōu)點(diǎn)正如上面所說的,能夠快速方便的定位到依賴的定義及使用,其確定就在于因?yàn)樾枰?Kotlin?支持,所以需要向項(xiàng)目中引入?Kotlin?的依賴,并且各個(gè)?module
?的?build.gradle
?配置文件需要轉(zhuǎn)換為?build.gradle.kts
?格式。
使用?Composing Builds?配置
Composing Builds
?方案的本質(zhì)和?buildSrc
?方案是一樣的,都是將對(duì)應(yīng)?module
?中的代碼編譯作為插件,在?build.gradle.kts
?中可以直接引用,那為什么還要有?Composing Builds
?這種方案呢?這是因?yàn)?buildSrc
?方案中,如果?buildSrc
?中的配置有修改,會(huì)導(dǎo)致整個(gè)項(xiàng)目都會(huì)進(jìn)行重新構(gòu)建,如果項(xiàng)目較小可能影響不大,但如果項(xiàng)目過大,那這個(gè)缺點(diǎn)顯然是無法接受的,Composing Builds
?方案應(yīng)運(yùn)而生。
使用方式:
- 在項(xiàng)目根目錄創(chuàng)建?
module
?文件夾,名稱隨意,這里使用?plugin-version
,并在文件夾中創(chuàng)建?build.gradle.kts
?配置文件,內(nèi)容如下:
plugins { id("java-gradle-plugin") id("org.jetbrains.kotlin.jvm") version "1.7.10" } repositories { google() mavenCentral() gradlePluginPortal() } java { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } dependencies { // 添加Gradle相關(guān)的API,否則無法自定義Plugin和Task implementation(gradleApi()) implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.10") } gradlePlugin { plugins { create("version") { // 添加插件,下面是包名 id = "xx.xx.xx" // 在源碼路徑創(chuàng)建類繼承 Plugin<Project> implementationClass = "xx.xx.xx.VersionPlugin" } } }
- 創(chuàng)建源碼目錄及包路徑?
src/main/kotlin/xx.xx.xx
,在包中新建類?VersionPlugin
?繼承?org.gradle.api.Plugin
class VersionPlugin : Plugin<Project> { override fun apply(target: Project) { } }
- 在項(xiàng)目根目錄下的?
settings.gradle.kts
?文件中添加?includeBuild("plugin-version")
- 最后和?
buildSrc
?方案一樣,在源碼路徑下新增相關(guān)依賴配置,在各個(gè)?module
?中引用即可。
Version Catalogs?配置
從?Gradle 7.0
?開始,Gradle
?新增了?Version Catalogs
?功能,用于在項(xiàng)目之間共享依賴項(xiàng)版本,?Gradle
?文檔中列出的一下優(yōu)點(diǎn):
- 對(duì)于每個(gè)?
Catelog
?,Gradle
?都會(huì)生成類型安全的訪問器,可以輕松的在?IDE
?中使用,完成添加依賴; - 每個(gè)?
Catelog
?對(duì)生成的所有項(xiàng)目都可見,可以確保依賴版本同步到所有子項(xiàng)目; -
Catelog
?可以聲明依賴關(guān)系包,這些捆綁包是通常在一起使用的依賴關(guān)系組; -
Catelog
?可以將依賴項(xiàng)的組、名稱和實(shí)際版本分開,改用版本引用,從而可以在多個(gè)依賴項(xiàng)中共享版本聲明。
接下來我們來學(xué)習(xí)這種方案的具體使用。
開始使用
使用?Version Catalogs
?首先當(dāng)然是需要項(xiàng)目?Gradle
?版本高于?7.0
,之后在項(xiàng)目根路徑下的?settings.gradle.kts
?中添加配置(因?yàn)樽髡唔?xiàng)目用的是?.kts
,groovy
?按對(duì)應(yīng)語法添加即可)
dependencyResolutionManagement { // 版本目錄配置 versionCatalogs { // 創(chuàng)建一個(gè)名稱為 libs 的版本目錄 create("libs") { // 聲明 groovy 依賴 library("groovy-core", "org.codehaus.groovy:groovy:3.0.5") } } }
在上面的配置之后,你就可以在項(xiàng)目中使用對(duì)應(yīng)依賴了。例:build.gradle.kts
dependencies { implementation(libs.groovy.core) }
這里有細(xì)心的小伙伴就會(huì)發(fā)現(xiàn),我們聲明的是?groovy-core
,使用的時(shí)候卻是?libs.groovy.core
,這是因?yàn)?Version Catalogs
?在根據(jù)別名生成依賴時(shí)對(duì)安全訪問器的映射要求,別名必須由?ascii
?字符組成,后跟數(shù)字,中間分隔只支持?短劃線-
、下劃線_
、點(diǎn).
,因此聲明別名時(shí)可以使用groovy-core
、groovy_core
、groovy.core
,最終生成的都是?libs.groovy.core
。
使用?settings.gradle.kts?配置
就如上面的示例中,我們就是在?settings.gradle.kts
?中聲明了?groovy-core
?的依賴,并且需要的地方使用,接下來我們?cè)敿?xì)說明對(duì)依賴項(xiàng)聲明的語法:
dependencyResolutionManagement { // 版本目錄配置 versionCatalogs { // 創(chuàng)建一個(gè)名稱為 libs 的版本目錄 create("libs") { // 聲明 kotlin 版本 version("kotlin", "1.7.10") // 聲明 groovy 版本 version("groovy", "3.0.5") // 聲明 groovy 依賴 library("groovy-core", "org.codehaus.groovy:groovy:3.0.5") // 聲明 groovy 依賴 library("groovy-nio", "org.codehaus.groovy", "groovy-nio").version("3.05") // 聲明 groovy 依賴使用版本引用 library("groovy-json", "org.codehaus.groovy", "groovy-json").versionRef("groovy") // 聲明 groovy 依賴組 bundle("groovy", listOf("groovy-core", "groovy-json", "groovy-nio")) // 聲明 kotlin 序列化插件 plugin("kotlin-serialization", "org.jetbrains.kotlin.plugin.serialization").versionRef("kotlin") } } }
這種方式相對(duì)統(tǒng)一了依賴版本,卻無法做到多項(xiàng)目統(tǒng)一。
使用?libs.versions.toml?配置
還是先看示例代碼:
dependencyResolutionManagement { // 版本目錄配置 versionCatalogs { // 創(chuàng)建一個(gè)名稱為 libs 的版本目錄 create("libs") { // 不能如此配置,會(huì)拋出異常 from(files("./gradle/libs.versions.toml")) // 可以添加此配置 from(files("./gradle/my-libs.versions.toml")) } // 創(chuàng)建一個(gè)名稱為 configLibs 的版本目錄 create("configLibs") { // 添加配置文件 from(files("./gradle/configLibs.versions.toml")) } } }
在配置版本目錄后,出了直接在?.kts
?里面添加依賴定義,還可以通過?from
?方法從?.toml
?文件中加載,.toml
?文件一般放在項(xiàng)目根路徑下的?gradle
?文件夾中。
這里需要注意的是,gradle
?有一個(gè)默認(rèn)配置名稱為?libs
,如果你創(chuàng)建的版本目錄名稱是?libs
,那么你就無需通過?from
?方法加載?libs.versions.toml
?文件,因?yàn)?gradle
?會(huì)默認(rèn)此配置,你只需在?./gradle
?路徑下創(chuàng)建?libs.versions.toml
?文件即可,重復(fù)添加會(huì)導(dǎo)致編譯失敗;如果你已經(jīng)有了一個(gè)?libs.versions.toml
?你也可以在添加以下配置來修改默認(rèn)配置名稱:
dependencyResolutionManagement { defaultLibrariesExtensionName.set("projectLibs") }
如果你創(chuàng)建的版本目錄名稱不是默認(rèn)配置名稱,那么就需要你手動(dòng)添加?from
?方法加載配置;所有版本目錄名稱建議以?Libs
?結(jié)尾,否則會(huì)有?warning
,提示后續(xù)將不支持此命名。
接下來我們來看?.toml
?文件的配置規(guī)則:
# 聲明版本號(hào) [versions] kotlin = "1.7.10" groovy = "3.0.5" # 聲明依賴 [libraries] # groovy groovy-core = "org.codehaus.groovy:groovy:3.0.5" groovy-json = { module = "org.codehaus.groovy:groovy-json", version = "3.0.5" } groovy-nio = { group = "org.codehaus.groovy", name = "groovy-nio", version.ref = "groovy" } # 聲明依賴組 [bundles] groovy = ["groovy-core", "groovy-json", "groovy-nio"] # 聲明插件 [plugins] kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
這種方式在統(tǒng)一單一項(xiàng)目依賴版本的同時(shí),可以通過分享?.toml
?文件來達(dá)成多項(xiàng)目依賴版本的統(tǒng)一,但是同樣的,同樣的文件在不同項(xiàng)目中不可避免是會(huì)被修改的,用著用著就不一致了。
使用插件配置
雖然從本地文件導(dǎo)入很方便,但是并不能解決多項(xiàng)目共享版本目錄的問題,gradle
?提供了新的解決方案,我們可以在一個(gè)獨(dú)立的項(xiàng)目中配置好各個(gè)三方依賴,然后將其發(fā)布到?maven
?等三方倉庫中,各個(gè)項(xiàng)目再從?maven
?倉庫中統(tǒng)一獲取依賴
插件配置
為了實(shí)現(xiàn)此功能,gradle
?提供了?version-catalog
?插件,再配合?maven-publish
?插件,就能很方便的生產(chǎn)插件并發(fā)布到?maven
?倉庫。
新建?gradle
?插件項(xiàng)目,修改?build.gradle.kts
plugins { `maven-publish` `version-catalog` } // 版本目錄配置 catalog { versionCatalog { // 在這里配置各個(gè)三方依賴 from(files("./gradle/libs.versions.toml")) version("groovy", "3.0.5") library("groovy-json", "org.codehaus.groovy", "groovy-json").versionRef("groovy") } } // 配置 publishing publishing { publications { create<MavenPublication>("maven") { from(components["versionCatalog"]) } } }
這里需要注意的是,插件項(xiàng)目的?gradle
?版本必須要高于?7.0
?并且低于使用該插件的項(xiàng)目的版本,否則將無法使用。
插件使用
配置從?maven
?倉庫加載版本目錄
dependencyResolutionManagement { // 版本目錄配置 versionCatalogs { // 創(chuàng)建一個(gè)名稱為 libs 的版本目錄 create("libs") { // 從 maven 倉庫獲取依賴 from("io.github.wangjie0822:catalog:1.1.3") } } }
重寫版本
從?maven
?倉庫中獲取版本目錄一般來講就不應(yīng)該修改了,但是僅一份依賴清單怎么滿足我們的開發(fā)需求呢,不說各個(gè)依賴庫都在不斷的持續(xù)更新,如果我們需要使用的依賴沒有在版本目錄里面聲明呢?我們不可能為了修改一個(gè)依賴的版本或者添加一個(gè)依賴就頻繁的發(fā)布Catalog
插件版本,這樣成本太高,這就需要我們進(jìn)行個(gè)性化配置了
dependencyResolutionManagement { // 版本目錄配置 versionCatalogs { // 創(chuàng)建一個(gè)名稱為 libs 的版本目錄 create("libs") { // 從 maven 倉庫獲取依賴 from("io.github.wangjie0822:catalog:1.1.3") // 添加倉庫里面沒有的依賴 library("tencent-mmkv", "com.tencent", "mmkv").version("1.2.14") // 修改groovy版本 version("groovy", "3.0.6") } } }
請(qǐng)注意,我們只能重寫版本目錄里面定義的版本號(hào),所以在定義版本目錄時(shí)盡量將所有版本號(hào)都是用版本引用控制。
使用方式
上面說了那么多的配置定義方式,下面來看看Version Catalogs
的使用方式:
plugins { // 可以直接使用定義的 version 版本號(hào) kotlin("plugin.serialization") version libs.versions.kotlin // 也可以直接使用定義的插件 alias(libs.plugin.kotlin.serialization) } android { defaultConfig { // 其它非依賴的字段可以在版本目錄的版本中定義 通過 versions 獲取 minSdk = configLibs.versions.minSdk.get().toInt() targetSdk = configLibs.versions.targetSdk.get().toInt() versionCode = configLibs.versions.versionCode.get().toInt() versionName = configLibs.versions.versionName.get() } } dependencies { // 使用 groovy 依賴 implementation(libs.groovy.core) // 使用包含 groovy-core groovy-json groovy-no 三個(gè)依賴的依賴組 implementation(libs.bundles.groovy) // 使用 configLibs 中定義的依賴 implementation(configLibs.groovy.core) }
上面我們已經(jīng)說過這種方案的優(yōu)點(diǎn),可以讓我們?cè)谒许?xiàng)目中保持依賴版本的統(tǒng)一,甚至可以分享出去讓其他開發(fā)者使用;同時(shí)也有著和?buildSrc
、Composing Builds
一樣的可跳轉(zhuǎn)、可追溯的優(yōu)點(diǎn);
但是相比于這兩個(gè)方案,Version Catalogs
生成的代碼只有默認(rèn)的注釋,并且無法直接看到使用的依賴的版本號(hào),而在?buildSrc
、Composing Builds
?中我們能夠?qū)σ蕾嚨墓δ苓M(jìn)行詳細(xì)的注釋,甚至添加上對(duì)應(yīng)的使用文檔地址、Github 地址等,如果支持自定義注釋,那這個(gè)功能就更完美了。
總結(jié)
Android?發(fā)展至今,各種新技術(shù)層出不窮,版本管理也出現(xiàn)了很多方案,這些方案并沒有絕對(duì)的優(yōu)劣,還是需要結(jié)合實(shí)際項(xiàng)目需求來選擇的,但是新的方案還是需要學(xué)習(xí)了解的。
原文鏈接:https://juejin.cn/post/7130530401763737607
相關(guān)推薦
- 2022-12-02 C語言中qsort函數(shù)用法及用冒泡排序?qū)崿F(xiàn)_C 語言
- 2022-01-21 如何保證Redis緩存與數(shù)據(jù)庫的一致性?
- 2023-04-19 nginx: [error] CreateFile() “D:\nginx-1.21.6/logs/
- 2022-10-10 YOLOv5改進(jìn)之添加SE注意力機(jī)制的詳細(xì)過程_python
- 2022-10-11 python嵌套try...except如何使用詳解_python
- 2022-12-31 go操作Kafka使用示例詳解_Golang
- 2022-04-21 Android?App頁面滑動(dòng)標(biāo)題欄顏色漸變?cè)斀鈅Android
- 2023-06-17 Python結(jié)合Sprak實(shí)現(xiàn)計(jì)算曲線與X軸上方的面積_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支