Gradle按repositories声明顺序逐个查找依赖,命中即止;本地缓存优先于mavenLocal(),再依次查找远程仓库;settings.gradle中dependencyResolutionManagement块优先级最高,覆盖各build.gradle配置。

Gradle按声明顺序逐个仓库查找依赖
Gradle不会并行扫描所有仓库,也不会智能选择“最可能有”的那个——它严格按 repositories 块中出现的顺序,一个一个试,找到第一个匹配的构件就立刻停止。这个“第一个命中者”规则是排查依赖失败的核心前提。
- 如果
google()放在mavenCentral()前面,而你要的androidx.core:core-ktx:1.12.0在两个仓库都存在,Gradle 一定用google()里的版本,哪怕mavenCentral()的版本更新或更稳定 - 一旦某个仓库返回了 POM 文件(哪怕内容不全或含错误依赖树),Gradle 就不会再继续往后查,这可能导致隐性冲突或解析失败
- 仓库顺序错误的典型现象:Sync 成功但运行时报
NoClassDefFoundError或NoSuchMethodError,因为加载了旧版 API 的 jar
settings.gradle 中的 pluginManagement 和 dependencyResolutionManagement 优先级更高
从 Gradle 7.0+ 开始,settings.gradle 里定义的仓库会覆盖 build.gradle 中同名配置。尤其要注意两个关键块:
-
pluginManagement { repositories { ... } }:只影响插件(如com.android.application)的下载,和普通依赖无关 -
dependencyResolutionManagement { repositories { ... } }:统一控制整个项目(包括所有子模块)的普通依赖查找顺序,其声明的仓库会完全替代各build.gradle里的repositories - 如果你在
build.gradle里写了mavenCentral(),但在settings.gradle的dependencyResolutionManagement里没写它,那它根本不会生效
本地缓存和本地 Maven 仓库也参与查找链路
仓库顺序只是远程部分;完整查找路径其实是:本地缓存 → 本地 Maven(mavenLocal())→ 远程仓库(按顺序)。
-
~/.gradle/caches/modules-2/files-2.1/是第一道关卡,命中即返回,不发网络请求 -
mavenLocal()对应~/.m2/repository/,它被当作一个“远程仓库”参与顺序查找,不是最高优先级——如果你把它写在repositories最前面,它才优先;否则它就排在你写的其他仓库之后 - 误以为
mavenLocal()总是优先,结果把本地改坏的 snapshot 版本一直用着,却查不到问题出在哪儿
调试依赖查找过程的实际命令
光看配置容易误判,真正要确认 Gradle 实际走了哪条路径,得靠日志和扫描工具:
- 执行
./gradlew build --scan,上传后在 Dependencies → Resolution Rules 页面能看到每个依赖具体从哪个仓库拉的 - 加
--info参数:./gradlew dependencies --configuration implementation --info,搜索 “Looking for” 和 “Found in” 关键字 - 如果某依赖始终报
Could not resolve,先检查它是否真的存在于你配置的某个仓库中——直接浏览器访问https://dl.google.com/dl/android/maven2/androidx/core/core-ktx/1.12.0/core-ktx-1.12.0.pom这类 URL 更快
最容易被忽略的是 dependencyResolutionManagement 块的存在与否——它让整个项目的仓库逻辑从分散走向集中,但很多人还在子模块的 build.gradle 里反复写 repositories,结果改了也不生效。











