1 Gradle的一些概念
Android Studio默许的构建东西为Gradle。在运用Gradle的进程中会碰到一些概念,理清他们的意义联系对咱们运用和深化理解Gradle至关重要。
1.1 Gradle 、AGP(Android Gradle Plugin)、 buildTools分别是什么,他们之间什么联系?
1.1.1 Gradle
Gradle是根据JVM的构建东西。他自身运用jave写的,gradle的脚本也便是build.gradle通常是用groovy言语。
1.1.2 Android BuildTools
Android SDK Build-Tools 是构建 Android apk、AAR文件等Android渠道产品所需的一个 Android SDK 组件,装置在 <sdk>/build-tools/
目录下。
//build-tools/
├── ⋮
├── aapt2
├── d8
├── apksigner
├── zipalign
├── ⋮
- AAPT2:Android 资源打包东西)是一种构建东西,Android Studio 和 Android Gradle 插件运用它来编译和打包运用的。AAPT2 会解析资源、为资源编制索引,并将资源编译为针对 Android 渠道进行过优化的二进制格式
- apksigner:东西为 APK 签名,并保证 APK 的签名将在该 APK 支撑的一切版别 Android 渠道上成功经过验证
- d8:Android Gradle 插件运用该东西来将项目的 Java 字节码编译为在 Android 设备上运行的 DEX 字节码
- Zipalign:在将 APK 文件分发给最终用户之前,先运用
zipalign
进行优化
1.1.3 Android Gradle Plugin
是根据Gradle的插件,Android Gradle 首要便是调用[Android BuildTools]这个包里的东西完结编译打包Apk等功能。
注:AGP3.0.0或更高版别,插件会运用默许版别的build Tools无需指定。
android { buildToolsVersion "33.0.1"}
1.2 gradleWrapper、gradle-user-home、GradleHome
1.2.1 GradleWrapper
项目的根目录的gradle/wrapper下
/gradle/wrapper/
├── gradle-wrapper.jar
└── gradle-wrapper.properties
担任下载办理特定版别的gradle,保证不同环境中项目运行在相同个gradle版别里,还能到达复用效果。
- gradlewraper目录下的gradle.jar负载下载gradle
- gradle-wrapper.properties内指定gradle的版别,下载地址,本地方位等装备信息。
1.2.1 GRADLE-USER-HOME
gradle-user-home
├── caches // modules-2和jars-3缓存依靠和产品,且各个版别各个项目中共用
│ ├── jars-3
| ├── transforms-3
│ └── modules-2
├── wrapper //存放不同版别的gradle
│ └── dists
│ ├── ⋮
│ └── gradle-7.4-bin
| └── xxxxxxxx
| └──gradle-7.3.3 //其实这是gradle home路径
└── gradle.properties
默许在方位位于/.gradle。这个目录下包括用户自界说的设置、maven本地仓库、gradle wrapper版别、gradle插件和一些缓存。其间该路径下caches文件夹有repo缓存也便是项目的依靠缓存,这个缓存各个项目是公用的,提升编译速度。
1.2.3 Gradle Home
gradle-home
├── bin
│ ├── gradle.bat
│ └── gradle
├── init.d
│ ├──..
│ └── xx.gradle
└── lib
├──...
├── gradle-wrapper-7.3.3.jar
├── gradle-tooling-api-7.3.3.jar
├──...
└── plugins
├── ...
├── gradle-publish-7.3.3.jar
├── commons-codec-1.15.jar
└──...
其实便是gradle的装置目录,里面首要包括Gradle 的可履行文件、库文件、插件等,gradle履行时会自动加载运用装置目录内的文件插件。
2 Gradle生命周期
Gradle履行构建是有生命周期的,分三个阶段初始化阶段(Initialization Phases),装备阶段(Configuration Phases)和履行阶段(Execution Phases)。
2.1 初始化阶段
- 履行init.gradle脚本:init.gradel脚本能够放置在gradle-user-home目录下、gradle-user-home/init.d/和gradle-home/init.d/目录下,其间后两者下的脚本称号只要一.gralde结束即可。他们的履行顺序为依次履行。在脚本里咱们能够设置一些个性化的装备,如装备repo源、鉴权等。
- 履行setting脚本:gradle会嗅探项目里的settings文件,settings文件中界说哪些项目参加到构建中。在settings.gradle文件中能够设置一些对一切参加的构建的项目做装备,也能够有针对性的做装备。
- 创立project实例:为参加到构建中的项目创立project实例。咱们在项目的build.gradle脚本里运用的project目标便是在这个时机创立的。
2.2 装备阶段
- 运用插件:下载运用声明的插件,脚本里有两种写法一种是apply plugin和plugins{}。他们的差异暂不作打开。
- 装备特点:给插件做参数装备,咱们最熟悉的android{}闭包其实便是对AGP里的com.android.application插件做参数装备。
- 运用依靠:gradle脚本中声明运用的依靠也会在装备阶段下载运用。
- 构建有向无环task使命图。
*注意:*履行任何task都会走初始化阶段和装备阶段
2.3 履行阶段
履行上一个阶段也便是装备阶段结构好的有向无环图使命。
tasks.register('test') {
println '该语句会在装备阶段履行'
doLast {
println '该语句会在履行阶段运行'
}
}
3 监听Gradle生命周期回调
3.1 监听初始化阶段回调
初始化阶段首要有两个能接回收调的地方settingEvaluated{}和 gradle.projectsLoaded {}
//settings.gradle装备履行完结
gradle.settingsEvaluated {
...
}
settingEvaluated{}setting创立加载成功。在此之前有几项gradle有几项重要的工作现已完结。
- gradle.properties 加载完结
- init脚本履行完结
- Settings目标创立成功,并且从gradle.properties加载的值也注入到了settings中
// 一切 Project 目标创立(注意:此刻 build.gradle 中的装备代码还未履行)
gradle.projectsLoaded {
...
}
初始化阶段还有扫描项目下的一切包括位于根project和子project中的build.gradle并对应生成Project目标,目标创立完结之后就会调用gradle.projectsLoaded{},但注意此刻build.gradle 中的装备代码还未履行。
3.2 装备阶段的回调
装备阶段会对项目下的每个build.gradle进行装备,如上图,beforeProject{}/project.beforeEvaluated{}和afterProject{}/after.beforeEvaluate会履行屡次,这取决于构建项目下有几个project。
- beforeProject{}/project.beforeEvaluated{}:会在每个project装备之前调用.
- afterProject{}/after.beforeEvaluate:会在build.gradle脚本”从头跑到尾”之后调用。
- 当一切的gradle.build都履行结束后,会调用projectEvaluted{}
- 最终,task图构建完结后,回调gradle.taskGraph.whenReady {}和gradle.taskGraph.taskExecutionGraphListener.graphPopulated()
3.3 hook履行阶段
每个task履行前后,咱们也有方法去监听:首要是运用gradle.taskGraph.beforeTask{} 和gradle.taskGraph.afterTask {},如下:
gradle.taskGraph.beforeTask { Task task ->
println "executing $task ..."
}
gradle.taskGraph.afterTask { Task task, TaskState state ->
if (state.failure) {
println "FAILED"
}
else {
println "done"
}
}
- !!!注意: 这些办法在gradle8.0现已直接被移除掉了统统不能用,原因简单的说便是影响cofigurationCache详细看这儿: task_execution_events
- 替代的方法:运用build_service
4 Gradle项目结构
root-project
├── buildSrc
| ├── ...
│ └── build.gradle
├── sub-project
│ └── build.gradle
├── build.gradle
├── settings.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew(Unix Shell script)
└── gradlew.bat(Windows batch file)
4.1 buildSrc
- buildSrc是位于gradle项目根目录的特殊目录,咱们能够在这编写Gradle的插件和使命。
- 这儿面的代码会在gardle的装备阶段履行。
4.2 gradle.Properties
- 在gradle-user-home目录下,项目根目录下和子项目目录下(和build.gradle同级)下都能够存在。
- gradle.properties界说的值有些时装备gradle环境特点,也能够增加自己自界说的特点,在咱们的构建脚本中能够直接访问这些值。
//gradle.properties中
mVersionName=1.12.1
//build.gradle
println("mVersion name in gradle.properties ${mVersionName}")
4.3 build.gradle和settings.gradle 文件
Gradle国际里经过初始化阶段后,build.gradle文件会对应生成Poject目标,settings.gradle文件会生成Settings目标,其实还有Gradle目标,每次构建启动时就会创立。
5 plugin 与 task
5.1 Gradle Plugin
Gradle是一个构建框架,自身不具备特别强的构建才能,详细构建才能依托于Gradle Plugin ,比如要打包APK就要依托AGP。AGP 内部经过调用Android Build Tool 去详细履行诸如编译class,打包资源等使命。
5.1.1 Apply plugin方法引进
Gradle Plugin的是运用首先是引进,就跟咱们在项目里需求某个第三方库需求引进相同。在跟目录的build.gradle中就可声明这些依靠,然后在构建脚本里声明运用,然后做装备。
//in rootproject/build.gradle
buildscript {
...
dependencies {
classpath:'com.android.tools.build:gradle:x.x.x'
}
}
//in subProject/build.gradle
apply plugin: 'com.android.application'//用于打包生成Apk
android {//构建Apk的装备
}
//in subProject2/build.gradle
apply plugin: 'com.android.library'//用于打包产出AAR
android{ //构建发生aar装备
}
如果在脚本gradle脚本中想运用一个第三方库,也需求经过classpath引进,然后就能够在脚本中运用了,示例如下。
//in root project build.gradle
buildscript {
dependencies {
classpath: 'com.squareup.okhttp3:okhttp:3.14.9'
}
}
import okhttp3.OkHttpClient
task("checkClasspath").doFirst {
//在脚本中运用引进了的okhttp
def client = new OkHttpClient()
..,
}
5.1.2 plugin{}脚本块引进
以上这种运用plugin的方法是分两步【引进+运用】,gradle还有引进和运用一步搞定的方法。
plugin{ id 'com.android.library' version 'x.x.x' }
默许的这种不需求引进就能运用插件的方法,插件来源只能是gradle 插件官网plugins.gradle.org/,如果想运用自己的插件需求在pluginManagement中装备源如下
//settings.gradle
pluginManagement {
repositories {
maven {
url './maven-repo'
}
}
}
5.1.3 其他
Gradel插件分两种:二进制插件和脚本插件;二进制插件便是被打包成了jar包的插件。脚本插件.gradle文件能够被作为插件运用。这种插件的运用只能经过apply plugin方法不能运用plugin{}的方法。
//config.gradle中
ext {
mVersion = '1.1.0'
}
//build.gradle
apply from: "../config.gradle"
println("mVersion${ext.mVersion}")
5.2 Task
5.2.1 履行动作
- 上文也提到过,gradle的一次构建,便是一系列task的履行,task便是gradle的一个履行单元。
- 一个gradle项目中包括若干个project,每个project中包括若干个task。
- 一个gradle task里面会包括若干个action。
5.2.2 创立task
task一般都界说在plugin中,咱们也能够自己界说task,给其装备姓名,描绘,分组,action,依靠联系等。
//build.gradle
project.tasks.register("aTask") {
println 'in configuration phase'
it.description("this is a sample task")
it.dependsOn("hello")
group("build")//IDE右边的Gradle便利东西栏中,会看到该task被归类到build分组内,便利查找
description "this is a gradle hello sample" //描绘
it.doLast {
println("do action >>1") //向当时task的action链路后追加action
}
it.doFirst {
println("do aciton >>2")//向当时task的action链路前查action
}
}
project.tasks.register("hello") {
it.doLast {
println("hello task is excuted-")
}
}
以上只是一个简单的比如,task的创立运用能够单开一个章节。
6 结
本文首要是在一个可能比较高的视角,谈了谈gradle相关的概念,生命周期特性,插件task等。把握了这些之后,还有一些更深化更详尽的论题值得探索。比如
- 自界说插件,详尽的Task详解
- gradle tansformer
- 构建性能怎么提升
- AGP常见的装备
- Gradle项目实战
今后会写系列文章去逐个探索,关注作者获取更新。
写文不易,过错不足之处望不吝赐教,点赞鼓励