本文记录的是今天在群里提到的昨天所踩的一个坑,有关 AndroidStudio 缓存的。java
先说一下背景。
我负责的一个项目,对一个图表库有外部依赖。这个图表库是我在维护的,因为新功能在开发中,因此我就使用了 SNAPSHOT 版本发布到 OJO(oss.jfrog.org) 上。我在项目中刚更新了依赖,突然想到还少几个 API,因而发布了 SNAPSHOT 版本。
故事就这样开始了。android
这时候回到 AndroidStudio 再去 Sync Project with Gradle Files
确定是拉不下来的。众所周知,Gradle 的缓存策略中,对于 SNAPSHOT 版本默认的缓存周期是 24 小时,也就是从我上次更新以后,24小时内都会使用上次的缓存。程序员
不周知的也不要紧,我在这里补充说明一下,在 Gradle 用户指南的依赖管理一章中,有提到 Gradle 对于动态版本和变化模块的缓存时间默认是 24 小时。
何为动态版本?你见过的像3.+
这种就是动态版本,它会取检查到的最高的版本号。又好比latest.integration
,它也是动态版本。
而变化模块,就是像0.2-SNAPSHOT
这种后面带SNAPSHOT
的版本了。
这二者的区别就是,前者尽管你代码中的版本号写法不变,但实际上它仍然是去取仓库的最新版本。然后者它在仓库中的版本号仍是同样,仍然是xxx-SNAPSHOT
,但实际上这个版本所对应的内容已经变了。缓存
这里再多说几句,缓存周期也是能够修改的,在 Gradle 用户指南中一样有详细说明,就是添加以下配置:服务器
只是这里我一开始就贪省事,在更新依赖懒得去改。app
既然如此,那怎么办?把 ~/.gradle/caches
整个给干掉?
不不不,那样过小题大作。其实这个问题我早已遭遇过,而且对于“汉化”过一遍 Gradle 用户指南的我来讲太简单了。命令行下执行:运维
这里啰嗦一下,aTD
是项目中一个 Gradle 任务的缩写,全名是 assembleTestingDebug
,其中 Testing
是项目里的一个 ProductFlavor
。这并不重要,重点是后面的参数 --refresh-dependencies
,加上这个参数,表示强制刷新依赖。
可是回到 AndroidStudio 写代码,发现代码提示中新的 API 仍是没有出来。看来是 Android Studio 没有更新。不过不要紧,这事我也有经验。点开右边的 Gradle 面板,找到 androidDependencies
任务,右键,Create xxxxx Configuration
,而后在弹出的面板的 Arguments 一栏中输入前面提到的参数 --refresh-dependencies
,添加完,在运行那里选择它执行。
等执行完,按照几年前的经验,这时候应该出来了吧?maven
然而,实际上并无。
这时候我突然想起,咱们公司在阿里云服务器上搭建了一个 maven 私服,去年的时候我在上面配置了对 OJO 的代理,这时候拉取的是私服上的版本,是它没有更新?
不要紧,解决方法很简单,删!
因而我登陆到 nexus 上,找到缓存的这个库,右键,整个版本删掉。删了服务器上的以后,还以为不放心,因而再把 .gradle 里的缓存给找出来删掉,我当时应该是这样子的: 编辑器
使用 nexus 搭建 maven 私服有几种好处,一是能够放公司内部的库;二是配置对其余 maven 仓库的代理,当有人去访问某一个依赖时它就会缓存下来,下次其余人再访问同一个依赖的话它就会直接取缓存,对于一些在国内访问不是很友好的仓库如 jcenter,能有效减小等待时间。固然若是公司内部局域网部署一个的话,提高效果会更显著。ide
最后再执行前面步骤。命令行中已经能够看到从新下载了这个依赖了,而且我也检查了 .gradle/caches/modules-2
下对应的源码 jar 包,确实是更新了。
再回到 Android Studio,发现依然没有更新。
这什么状况?
我疑惑了一下,心中一个声音响起:
啊(这里应读四声)!
这时候我想到了,新版的 Android Studio 为了提速,多了一层缓存:对于第三方依赖会把它们解压出来,放到 ~/.gradle/caches/transforms-1
目录中。
因而继续:
删!
而后再构建,让它从新缓存,这时候应该就能够了吧。
在 Android Studio 中执行了构建,而后发现它确实从新缓存了。可是——
悲剧就此发展,深坑就此塌陷!
这时候,我发现不单是新加的 API 没有出来,编辑器里有关这个库的代码全都变红了!尽管!项目仍是能跑起来!当时的屏幕是这样的:
不对不对。咋回事?
这时候我又机智地想到,这里缓存的路径有包含 hash 做为名称的文件夹,更新了以后,hash 值也不一样了,因此应该是哪里的索引没有对应上。因而找啊找,就在 transforms-1/metadata-1.1
中发现了一个叫 results.bin
的文件。再搜一下里面有没有包含那个库的内容:
提示是二进制文件。哦,那就加个参数:
结果出来了,果真有。那好,那就再删!
等等——我这时谨慎了一下,仍是重命名一下好了。因而重命名,而后再执行构建,而后看到这个文件从新生成了,看起来正朝预料中的发展。然而,有关这个库的引用仍是报错。
这时候的我陷入了一番沉思,再试其余方法:
Sync with File System
Sync Project with Gradle Files
File -> Invalidate Caches / Restart
仍是无效。带着郁闷,我下班了。
虽然这问题此刻表现得如此顽固,可是最终它仍是被我解决了。
早上一来,我以为我应该是有点急了,毕竟项目的开发时间由此被我拖多了一天了,可是做为一名有着一颗运维的心的程序员,本身踩陷的坑不管怎样也要把它踩平。
因而我开始往其余缓存方面上考虑,也没有去想合不合逻辑。我想到了 Gradle 在构建时会对一个任务的输入作快照,因而找到项目里的 .gradle/buildOutputCleanup
目录,删!
还不行,那就 .gradle/4.4
(当前使用的 Gradle 版本),删!
还不对,那就整个 .gradle
,删!
甚至,~/.gradle/caches/transforms-1/
,删!
依然不对,那就 Android Studio 的配置文件夹,~/.AndroidStudio3.1
,删!
删完从新打开 Android Studio 导入配置,这时候发现已经不是以前的问题了,你觉得问题解决了吗?不!是问题升级了!这时候已经不是那个库报红了,而是全部引用第三方库的地方都报红了!!!尽管,仍是能够运行起来!!
百般无奈之下,继续 google,看到的仍是前面提到的 Invilate Cache 的方法。突然在 Stackoverflow 中看到了一个看起来不是很常见的回答:
退出 Android Studio,删除全部的 .iml 文件以及 .idea 目录,打开 Android Studio 从新导入项目。
咦?这方法没试过。那就试试吧:
而后从新打开 Android Studio,点 Sync with File System
,这时候奇迹终于出来了,应该说,Android Studio 终于正常了,编辑器不报红了!
压抑着心中的万分激动,有着打破沙锅问到底精神的我,对此问题仍不放弃思考。
因此,到底是什么缘由呢?
我看了一下 .iml 文件,没什么异常。那就再看.idea 目录。
结果以下:
原来是在 .idea/libraries 里会记录每个第三方库的 classes, javadoc 以及 sources 所对应的路径。其中 classes 对应的正是前面所提到的 transforms-1 里的目录,一样也正如前面所说,其中包含的路径是有 hash 值的,更新了依赖以后,hash 值不一样,新的缓存路径也就不一样了,而这里仍是用的原来被删的那个路径,找不到对应的文件固然编辑器里就提示 cannot resolve symbol
了。因此正确而直接的解决方案应该是删除 .idea/libraries/
里对应该第三方库的 xml 文件让它从新生成,或者是直接修改该 xml 文件的内容,改成更新依赖以后的路径。