Gradle是Android Studio默认的构建工具,它提高了Android的开发效率,它的作用就是管理项目中的依赖、打包、编译
构建历史
- Apache Ant
Ant支持自动化打包逻辑 - Apache Maven
Maven比它多了自动下jar包,规范了打包逻辑,反而不好定制 - Gradle
Gradle既能自动下jar包,又能自己写脚本,而且脚本写起来比Ant便捷
maven仓库
- maven仓库:本地仓库+远程仓库
- 远程仓库:中央仓库+私服+其他
- 中央仓库:jcenter+mavencentral
- 私服:公司内部局域网
如果本地仓库没找到,会按照repositories中声明的仓库顺序,在私有仓库和中央仓库查找对应的类库,找到则将类库版本信息下载到本地仓库
POM
pom:全名Project Object Model 项目对象模型,用来描述当前maven项目发布模块的基础信息
举例(’com.android.tools.build:gradle:4.1.1’)
groupId 组织 / 公司的名称 com.android.tools.build
artifactId 组件的名称 gradle
version 组件的版本 4.1.1
packaging 打包的格式 aar
project build.gradle
1 | buildscript { |
module build.gradle
1 | repositories{ |
gradle支持的仓库类型
1 | repositories{ |
常用的中央仓库:
1 | google() |
国内镜像 阿里云
1 | maven { url 'http://maven.aliyun.com/nexus/content/repositories/google' } |
Release和SNAPSHOT
版本名:Release版本:1.0.0,SNAPSHOT版本:1.0.0-SNAPSHOT
Release版本如果版本没有更新不需要每次都去下载,除非本地仓库被清除,
而SNAPSHOT版本每次编译都需要去中央仓库更新版本信息
- snapshot打版-SNAPSHOT是必需含有的,deploy会发布到snapshot库,不含有-SNAPSHOT则为release版本,会发布到release库。
- maven更新依赖时-SNAPSHOT是实时拉取,release 则不会。
- 同一版本号上传到nexus仓库时,snapshot可以上传成功,release会上传失败
maven私服搭建
去官网下载 maven私服启动器nexus
https://juejin.cn/post/7118646272323485709
https://central.sonatype.com
发布github仓库
github需配合jitpack使用https://jitpack.io/
项目级build.gradle
1 | allprojects { |
发布mavencentral
详见:发布Gradle插件
Wrapper
wrapper里定义了gradle的版本
举例:
我现在的这个项目用的gradle版本是5.4.1的,那么这个版本是跟我现在的工程绑定的。若今后构建这个工程时,它都会用我所绑定的gradle版本(避免版本兼容性问题)所以wrapper的作用就是会来检查在你构建这个工程的机器上有没有5.4.1这个版本。如果有就开始构建,没有就去下载这个版本。再举个例子,假如你现在从网上下载了一个项目,而这个项目它所绑定的gradle版本是5.1.1的,而你的机器现在只有5.4.1版本的gradle,那么当这个项目在你这台机器上构建的时候,wrapper就会看你机器上有没有5.1.1版本的gradle,发现没有的话就会去到所提供的url下载这个版本。
build.gradle
1 | buildscript { |
buildscript
dependencies里面所要下载依赖的jar包都要去到repositories中所给你的仓库里去找
allprojects
buildscript下面的是gradle自身构建所需要的一些依赖;而allprojects下方的仓库则是给项目中的其他module去使用的,像app模块或者其他你自己新建的一些模块它们所需的依赖就是到allprojects下面所给的仓库里去找
gradle.properties和local.properties
local.properties
放的是一些系统配置(比如sdk路径)gradle.properties
这里放的是一些全局的配置文件,比如【android.useAndroidX=true】就是当前项目启用AndroidX
settings.gradle
这里面包含了你的子项目,也就是你项目中的module,假如刚新建好的项目那么就只包含一个’app’ module;如果你新建了其他module,它也会包含在这里面。在构建的初始化阶段,settings.gradle会提供这次构建项目所要包含的哪些module。
settings.gradle 对应一个 Settings 对象
build.gradle 对应一个 Project 对象
依赖管理
添加依赖:app > build.gradle > dependencies
1 | dependencies { |
添加仓库:project > build.gradle
1 | buildscript { |
如果不是google、maven仓库的话,需要自己手动在repositories{ }里配置仓库地址,新建项目这俩默认就有了
添加仓库:project > setting.gradle
1 | pluginManagement { |
Gradle7.0之后,repositories{ }配置由build.gradle迁移到settings.gradle文件
app > build.gradle
1 | plugins { |
- 本地模块:需要在settings.gradle中include声明
- 本地二进制文件:需要在build.gradle声明路径
- 远端二进制文件:上述示例,也是用的最多的一种
Jcenter MavenCentral 区别
- jcenter停止新服务了
- MavenCentral:
https://mvnrepository.com/
https://central.sonatype.com/
GAV(坐标): groupId + artifactId + version
api implementation 区别
- implementation:模块内
- api:具有依赖传递性,容易造成依赖冲突
./gradlew app:dependencies
可以查看依赖树
比如:androidx.annotation:annotation:1.1.0 -> 1.3.0
->:表示冲突,比如这个1.1.0 -> 1.3.0,-> 后面的版本表示Gradle决议之后的版本,
这里表示1.1.0版本被拉高到1.3.0
依赖决策
- 同一个模块的多个相同依赖,优先选择最高版本
- 多个模块的多个相同依赖,优先选择主模块(app)的版本,并默认有strictly关键字约束,
即使子模块的版本比app模块的版本高,也优先选择主模块(app)中依赖的版本 - force优先级高于strictly,如果二者同时显式声明,则会报错
- 同时使用force强制依赖版本时,版本决议的结果跟依赖顺序有关,最早force的版本优先
- 子级跟随父级:没有直接依赖okhttp的情况下,有多个retrofit依赖,okhttp的版本跟随高版本的retrofit
分类示例决议结果说明
- 全数字,段数不同1.2.3 vs 1.41.4段数依次比较,数字大的胜出
- 全数字,段数相同,位数相同1.2.3 vs 1.2.41.2.4同上
- 全数字,段数相同,位数不同1.2.3 vs 1.2.101.2.10同上
- 全数字,段数不同1.2.3 vs 1.2.3.01.2.3.0段数多的胜出
- 段数相同,字母比较1.2.a vs 1.2.b1.2.b字母大的胜出
- 段数相同,数字与非数字1.2.3 vs 1.2.abc1.2.3数字优先字母
Gradle插件
- 脚本插件:.gradle为后缀的文件,通过 apply from去引用
- 对象插件:实现org.gradle.api.plugins 接口的插件
- 自定义对象插件:
1、在 build.gradle 文件中直接编写
2、在 buildSrc 默认插件目录下编写
3、在自定义项目下编写
然后通过 apply plugin 的方式去引用这个插件
详情可查看【发布Gradle插件java】和【发布Gradle插件kotlin】
Gradle bug
出现诡异的gradle问题,可以删除gradle重新编译
比如:rm -r ~/.gradle/wrapper/dists/gradle-6.5-bin
参考文章:
https://juejin.cn/post/7215579793261117501
https://juejin.cn/column/7123935861976072199