Android 仓库解析
背景
Android Studio 引用的第三方库来自俩种网络仓库,一种是 Maven Center,另一种是 JCenter,俩种仓库功能没有区别。
由于 Maven Center 的种种问题,新版本的 AS 已将默认仓库替换为 JCenter,新项目会默认配置 jcenter()
而不是 mavenCentral
。
除此之外,Maven 仓库和 Gradle 会将经常使用的第三方库缓存到本地,不用每次使用都下载,因与远程仓库功能相似,这里称之为本地仓库。Android Studio 中存在俩种本地仓库:Gradle 和 Maven。
下面分别针对本地仓库(Maven、Gradle)、远程仓库(Maven、JCenter)作解析。
1 本地仓库
作用:本地仓库将经常使用的第三方库缓存到本地,不用每次使用都重新下载。
1.1 Maven 本地仓库
1.1.1 Maven 本地库配置方式
buildscript {
repositories {
mavenLocal()
}
}
allprojects {
repositories {
mavenLocal()
}
}
1.1.2 Maven 本地库默认地址
/Users/用户名/.m2
该地址为 mac 地址,默认是隐藏的,只有在配置后才会缓存。
仓库的查找有优先级,如果在引用仓库中找到了目标库,则不会在下面配置的地址仓库中查询。
所以如果配置应将 mavenLocal 填写为引用的第一个仓库,保证先从本地 Maven 库获取。
1.1.3 上传 aar 至 Maven 本地库
这里新建 Android Library,并命名为 library。上传 Module 生成的 library-debug.aar 文件需要在 library module 的 build.gradle 如下配置:
apply plugin: 'maven-publish'
publishing {
publications {
maven(MavenPublication) {
//上传到仓库的库文件
artifact "${buildDir}/outputs/aar/library-debug.aar"
groupId "com.app.xz.library"
artifactId "librarytest"
version "1.0.0"
}
}
}
配置完并点击 sync,Gradle 一栏会新出现下图标注的 Task:
Gradle-Task点击 publishToMavenLocal,即将 aar 文件发布到本地 Maven 库。
下面的配置方式可以实现和 publishToMavenLocal 同样的效果,二者选其一即可。
apply plugin: 'maven' uploadArchives { repositories.mavenDeployer { //仓库路径 def depath = file('/Users/xuzheng/.m2/repository') repository(url: "file://${depath.absolutePath}") pom.groupId = "com.app.xz.library"; pom.artifactId = "librarytest"; pom.version = "1.0.0"; } }
Gradle 一栏会添加 upload-uploadArchives 命令。
1.1.4 依赖 Maven 本地库 aar
依赖配置方式与传统方式没有区别。
implementation 'com.app.xz.library:librarytest:1.0.0'
1.1.5 调试
Q :当 Module 有内容更新时,重新发布更新后(没有升级版本)的 aar 到 Maven 本地库,然后项目 Rebuild,发现项目依赖的 aar 并没有如预期更新,这是为什么呢?
A :查看项目依赖。 依赖,可以发现项目依赖的本地库是 Gradle,下文将接着介绍 Gradle 本地库。
1.2 Gradle 本地仓库
1.2.1 Gradle 本地库默认地址
/Users/用户名/.gradle/caches/modules-2/files-2.1
该路径也是被隐藏的。
1.2.2 Gradle 本地库解析
首先,Gradle 本地仓库不需要额外配置。
然后,Gradle 本地仓库类似于 Maven 本地仓库,它会将网络下载的第三方库缓存到本地仓库里,下次使用时则直接从本地仓库获取。注意:Gradle 本地仓库不会缓存 Maven 本地仓库的依赖。
既然如此,为什么【Maven 本地仓库--调试】中会显示 Gradle,且 aar 没有更新呢?
原来,Android Studio Gradle 为了提速,多增加了一层缓存:对于三方依赖,会把它们解压出来放到
/Users/用户名/.gradle/caches/transforms-1
或 /Users/用户名/.gradle/caches/transforms-2
中,Maven 本地库虽然更新了,但是该层缓存还没有更新,所以解决办法是:删除依赖 → sync → 重新引入依赖,这样 AS 的缓存就会删除并重新从本地库解压,实现更新。
扩展
不知道大家有没有遇到下面描述的问题:
公司有自己的 sdk 仓库,频繁调试时,每次将 aar 发布到公司内网仓库里,如果版本不变,本地项目依赖时,aar 不会更新。会出现这种情况的原因是:
Maven 本地仓库的 aar 更新,是因为我们手动 publishToMavenLocal 的结果,而上面的描述只是手动更新了公司的远程仓库,Gradle 本地仓库并没有更新。所以解决办法是:
首先将 Gradle 本地仓库内的该依赖删除(本地没有依赖才能重新从网络拉取依赖),然后 build.gradle 删除依赖 → sync → 重新引入依赖(刷新 AS 自身缓存)。经过上面俩步操作,将俩层本地缓存彻底刷新,项目依赖才能得到正确更新。下文将会有远程仓库的分析,这段内容不理解可以后续回顾。
2 远程仓库
2.1 JCenter 远程仓库
作用:三方库资源共享。
关于 JCenter 网上教程很多,或者也可以自行去 官网 注册学习。
2.2 Maven 远程仓库
作用:通过搭建 Maven 私人远程仓库,提升多人协作开发效率。
Github 搭建私人 Maven 远程仓库
1.在 GitHub 创建仓库。(我这里由于创建过同名仓库所以会有红色警告)
Github 创建仓库2.将 Github 仓库与本地文件夹绑定。
Github 的基础用法,不清楚的可以参考下面说明,了解请跳过。
Github 仓库的初始化
1.首先在Github新建仓库,不要勾选init
2.在本地新建文件夹,依次如下执行命令:
2.1.initgit init
2.2.创建 README 文件
touch README.md
2.3.首次 commit
git add README.md git commit -m "first commit"
3.4.添加远程主机 git remote add <主机名> <网址>
git remote add origin https://github.com/zhxyComing/MyMaven.git
<5.首次push
git push -u origin master
这步首次要求输入 github 的用户名和密码.
3.之后就可以正常 commit、push 了
git push origin master
3.将 aar 上传到 Github 本地库。
apply plugin: 'maven'
uploadArchives {
repositories.mavenDeployer {
//Github 本地库文件夹路径
def depath = file('/Users/用户名/MyMaven')
repository(url: "file://${depath.absolutePath}")
pom.groupId = "com.app.xz.library";
pom.artifactId = "librarytest";
pom.version = "1.0.0";
}
}
执行 Gradle - uploadArchives 上传。
4.使用 Git 命令将我们的 aar 提交到远程仓库。
5.引用远程仓库依赖。
如下配置私人远程 Maven 仓库地址,将 github.com
替换为 raw.githubusercontent.com
,末尾追加需要的分支名。
buildscript {
repositories {
maven { url "https://raw.githubusercontent.com/zhxyComing/MyMaven/master" }
// mavenLocal()
}
...
}
allprojects {
repositories {
maven { url "https://raw.githubusercontent.com/zhxyComing/MyMaven/master" }
// mavenLocal()
}
}
至此从上传到依赖配置完毕。
题外话
组件化开发中,将 Module 打包成 aar 上传至远程仓库,如果 Module(aar) 还依赖了其它第三方库,则这些第三方库不会打包到 aar 中。如果主工程也不存在这些第三方库的依赖,那么项目运行中就会报 ClassNotDefFoundError。
针对上面问题,可以在主工程中引入依赖解决,但终究不够优雅。后续将会探讨如何将 module 的依赖库一并打入 aar,以及它的原理。
[toc]