先說結果
這是總結之後的init.gradle
配置,很直觀,好理解,位置在USER_HOME/.gradle/
allprojects {
repositories {
maven {
name "ALIYUN_CENTRAL_URL" // name 可以不需要
url 'https://maven.aliyun.com/nexus/content/repositories/central'
}
maven {
name "ALIYUN_JCENTER_URL"
url 'https://maven.aliyun.com/nexus/content/repositories/jcenter'
}
maven {
name "ALIYUN_GOOGLE_URL"
url 'https://maven.aliyun.com/nexus/content/repositories/google'
}
}
}
錯誤示例
你能搜到的幾乎所有文章的init.gradle都是這個:
(CSDN代碼塊不支持groovy高亮拿kotlin湊合了下)
allprojects {
repositories {
def ALIYUN_REPOSITORY_URL = 'http://maven.aliyun.com/nexus/content/groups/public'
def ALIYUN_JCENTER_URL = 'http://maven.aliyun.com/nexus/content/repositories/jcenter'
all {
ArtifactRepository repo ->
if (repo instanceof MavenArtifactRepository) {
def url = repo.url.toString()
if (url.startsWith('https://repo1.maven.org/maven2')) {
project.logger.lifecycle "Repository ${repo.url} replaced by $ALIYUN_REPOSITORY_URL."
remove repo
}
if (url.startsWith('https://jcenter.bintray.com/')) {
project.logger.lifecycle "Repository ${repo.url} replaced by $ALIYUN_JCENTER_URL."
remove repo
}
}
}
maven {
url ALIYUN_REPOSITORY_URL
url ALIYUN_JCENTER_URL
}
}
}
問題一
我們來看這個init.gradle
到底做了什麼:
1.定義阿里雲鏡像倉庫地址
2.如果項目裏引入了mevenCentral
或jcenter
,刪掉,打印一個log
3.引入阿里雲鏡像倉庫
這樣基本上沒有問題,實際上gradle關於init腳本的文檔中就有這麼寫的示例,但原示例的內容是"我只想使用公司內部的repo,其他倉庫我都不要",這並不符合我的需求,樸素的想法時:如果阿里雲鏡像有該依賴,優先使用阿里雲來加速;如果沒有,再去原有倉庫下載。
而上面的腳本在阿里雲鏡像沒有及時更新or其他原因沒有找到需要的庫時,依賴就會直接出錯。
事實上,gradle文檔中Declaring module dependencies部分提到:
A project can have multiple repositories. Gradle will look for a dependency in each repository in the order they are specified, stopping at the first repository that contains the requested module.
在有多個倉庫時,gradle會根據順序依次搜索依賴,在找到第一個符合條件的倉庫就不再看後面了。
init script部分中也有這樣的例子:
可以看出init.gradle
執行在build之前,在其中添加的內容最終會放在項目build.gradle
相同位置的前面。
然後所以上面腳本的第2步去刪掉原有倉庫是沒必要的。可以同時保留原倉庫和鏡像倉庫,init腳本會保證鏡像倉庫排在依賴順序的前面。
其實實際上阿里雲鏡像還是很全的(真的是不是我也不造啊),但有的文章就比較離譜,加一個阿里雲Jcenter,把mavenCentral都給刪了。
問題二
上面的腳本中,引入鏡像地址時是這樣寫的
maven {
url ALIYUN_REPOSITORY_URL
url ALIYUN_JCENTER_URL
}
這就純粹是不瞭解Groovy和Gradle DSL了,可以在AS中按住command(mac)點擊看這個url
的定義,它其實是一個void setUrl(Object url)
函數,所以寫兩個並不會都加上,前一個會失效
這也很奇怪,很多文章都提到在項目中添加鏡像和定義init.gradle
兩種方式,在項目中定義時就能分開寫maven {},到了init.gradle就千篇一律放一塊了。很神祕🤔。
補充
-
你可以看到我的配置裏多了一個鏡像倉庫地址,實際上阿里雲提供maven鏡像的不止這幾個,
可以在這裏找到,你喜歡的都可以往上加。
-
如果使用了定義
buildSrc
這種方式來管理gradle配置,init 腳本是會失效的 -
想要知道項目裏是否真的有依賴到鏡像倉庫,可以這樣:
- 在AS工程
build.gradle
中新增一個task,sync
buildscript {
...
}
allprojects {
...
}
// 寫個a方便後面截圖時排最前..
task aShowRepo {
println "All repos:"
println repositories.collect { it.name }
repositories.each {
println "repository: ${it.name} ('${it.url}')"
}
}
- 點開側邊欄,一路找到自定義的task,右鍵,選擇
Execute After Sync
3. 重新sync或者build項目,可以看到輸出,印證了init.gradle
中定義的倉庫確實會排在前面
沒毛病