问题是这样的,我自己写了一个日志库,发布到mavenCentral了,然后在使用这个库的时候,我配置了有阿里云仓库和官方仓库,但官方仓库排在后面,编译时失败,报了一个dataBindingMergeDependencyArtifactsNewDebug的异常,名字怪怪的,而且我的库中也没有配置dataBinding啊,日志如下:
bash
Execution failed for task ':imsdroid:dataBindingMergeDependencyArtifactsNewDebug'.
> Could not resolve all files for configuration ':imsdroid:newDebugCompileClasspath'.
> Failed to transform logback-android-0.0.3.aar (cn.android666:logback-android:0.0.3) to match attributes {artifactType=android-databinding, org.gradle.category=library, org.gradle.libraryelements=jar, org.gradle.status=release, org.gradle.usage=java-api}.
> Could not find logback-android-0.0.3.aar (cn.android666:logback-android:0.0.3).
Searched in the following locations:
https://maven.aliyun.com/repository/public/cn/android666/logback-android/0.0.3/logback-android-0.0.3.aar
https://maven.aliyun.com/repository/public/cn/android666/logback-android/0.0.3/logback-android-0.0.3.jar
Possible solution:
- Declare repository providing the artifact, see the documentation at https://docs.gradle.org/current/userguide/declaring_repositories.html
Fix with AI
从日志看,它从https://maven.aliyun.com/repository/public/cn仓库中查找不到aar依赖,然后就直接终止了,不再往下查找了。这很奇怪,因为我配置了4个仓库,如下:
bash
// google()仓库的的阿里云镜像
maven {
url = uri("https://maven.aliyun.com/repository/google")
}
// mavenCentral()仓库的阿里云镜像(同时包含jcenter()仓库)j
maven {
url = uri("https://maven.aliyun.com/repository/public")
}
// 备用官方仓库
google() // Android官方依赖
mavenCentral() // 第三方依赖
理论上说是从上往下查找到,从报错信息看,是提示在配置的第二个仓库(即"https://maven.aliyun.com/repository/public")中找不到依赖,然后就结束了,后面还有两个仓库都没去查找。
这说明起码第一个仓库已经找过了,而且没找到,但是也没有提示说第一个仓库找不到aar的异常信息啊,只是提示了在第二个仓库找不到aar,为什么会这样?
根据AI提问,可能的原因是这样的:
阿里云会同步MavenCentral中的依赖,但是可能同步不完全,或者有延迟,比如它可能只同步了pom文件,其它文件(如aar)还没同步到。
Gradle查找依赖的流程是这样的,先从仓库中查找pom,如果找不到,则继续去下一个仓库中找,如果找到了pom,则会认为这个依赖就在这个仓库中,于是在这个仓库中下载,但是此时阿里云仓库中还没把我的aar同步到它的服务器上,所以下载aar肯定失败,但是因为它有pom,所以gradle认为这个仓库有这个依赖,下载失败后,它就直结束了,不再去后面的仓库中查找了。所以第一个仓库中查找依赖了,没有pom,所以它直接找下一个仓库,也不会输出第一个仓库找不到的信息,而在第二个仓库找到pom了,但是没有aar,所以输出错误信息了。
解决方案如下:
kotlin
maven {
url = uri("https://maven.aliyun.com/repository/public")
metadataSources {
artifact()
}
}
这表示不依赖pom,而是直接下载aar,这种情况下如果下载失败的话会继承找下一个仓库。
但是也会有问题,如果直接下载aar,能下载到,它就不会找下一个仓库了,但是由于不依赖pom,但是aar中可能还依赖了别的库,这些别的库的信息是保存在pom中的,所以它不会下载传递的依赖,这也是个问题。
解决方案就是把 mavenCentral()移动最前面,以便Gradle先从这个仓库找。但这样就没有发挥到镜像仓库的优势了,比如有一个库在镜像中有,在mavenCentral中也有,那它直接就从mavenCentral仓库中获取了,但是它的速度慢啊。所以这样也不行。
于是再问AI,不配置metadataSources 的话,它的默认配置是什么,回答说是这样的:
kotlin
metadataSources {
gradleMetadata() // 优先查找 .module 文件
mavenPom() // 其次查找 .pom 文件
}
查找顺序:
- 先尝试下载 .module 文件
↓ 没有 - 再尝试下载 .pom 文件
↓ 没有 - 认为该仓库没有此依赖 → 继续去下一个仓库
而我的情况是,有pom,但是没有aar,所以没有继续去下一个仓库中找了。
解决方案如下:
kotlin
metadataSources {
gradleMetadata() // .module
mavenPom() // pom.xml
artifact() // 直接尝试 jar/aar
}
这样配置后,下载jar失败了,也会继续尝试找下一个仓库,而且也不会省略pom的摸找。
具体是不是这样的,我也不知道,这可能得读Gradle源码才能了解真正原理。
后来,过了一段时间,我想阿里云应该把我的aar给同步了吧,于是我把metadataSources 注释掉,结果还是报错依旧,于是我把它报错的那个aar链接复制到浏览器,明明是能下载的啊,说明有这个aar,但是它报错说没有。这就很神奇,于是再问AI,答案是有缓存,但是我配置成这样它又正常了,如下:
kotlin
metadataSources {
gradleMetadata() // .module
mavenPom() // pom.xml
}
如果说默认就是这这个的话,为什么我手动配置一下又正常了?难道是Gradle会根据我们的build.gradle.kt配置来使用缓存,虽然默认也是这个,但是因为我们手动加了它,Gradle在编译时觉得是配置变了,所以没读缓存结果,所以它就正常了?不知道是不是这样的。 AI对于Gradle缓存的回答如下:
Gradle 的缓存行为
Gradle 会缓存查找失败的结果 ,也叫 negative cache(负缓存):
第一次构建:
1. 去阿里云找 .aar → 404
2. 把"找不到"这个结果缓存到本地
3. 报错
第二次构建(即使阿里云上已经有了):
1. 发现本地有缓存记录:"这个文件不存在"
2. ❌ 直接用缓存结果,根本不去请求网络
3. 继续报错
缓存位置
~/.gradle/caches/modules-2/files-2.1/ ← 成功下载的文件
~/.gradle/caches/modules-2/metadata-2.*/ ← 元数据缓存(包含负缓存)
解决方法
方法一:强制刷新依赖(推荐)
这个方法我实验过,确实有用,别的方法没实验过。
bash
bash
./gradlew build --refresh-dependencies
推荐在gradle面板执行:
bash
build --refresh-dependencies
方法二:删除对应的缓存目录
bash
bash
# 删除该依赖的缓存
rm -rf ~/.gradle/caches/modules-2/files-2.1/cn.android666
rm -rf ~/.gradle/caches/modules-2/metadata-2.*/cn.android666
方法三:删除全部缓存(核弹级)
bash
bash
rm -rf ~/.gradle/caches/modules-2/
负缓存的有效期
Gradle 默认负缓存有效期是 24小时 ,超过后会重新请求网络。也可以在 gradle.properties 中修改:
properties
properties
# 设置为0表示每次都重新检查
org.gradle.cacheperiod=0
所以你很可能遇到的情况是:早期某次构建时阿里云确实没有同步好,Gradle 缓存了"找不到"的结果,后来阿里云同步好了,但 Gradle 一直在用旧的负缓存。