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:

Android 仓库解析_第1张图片
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 创建仓库。(我这里由于创建过同名仓库所以会有红色警告)

Android 仓库解析_第2张图片
Github 创建仓库

2.将 Github 仓库与本地文件夹绑定。

Github 的基础用法,不清楚的可以参考下面说明,了解请跳过。

Github 仓库的初始化

1.首先在Github新建仓库,不要勾选init
2.在本地新建文件夹,依次如下执行命令:
2.1.init

git 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]

你可能感兴趣的:(Android 仓库解析)