Gradle学习二
一、Gradle构建机制
1、settings.gradle
Gradle支持多工程构建,使用
settings.gradle
来配置添加子工程模块,settings文件在初始化阶段执行,创建Settings对象,在执行脚本时调用该对象的方法。
单模块项目并不一定需要setting文件,但是多模块项目必须要有setting文件,否则Gradle不知道哪个模块应包含在构建内。
Setting.include(String…projectPaths)
- 将给定的目录添加到项目构建中,’:app’表示文件相对路径,相当于’./app文件夹’。
- 多项目架构进行分层,把同层次的子工程放在同一文件夹下便于管理,使用’:xxx:yyy’表示
2、顶层构建文件:build.gradle
在项目中,所有模块的配置参数都应在顶层build.gradle文件中配置。默认情况的代码块如下:
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath "com.android.tools.build:gradle:4.1.1"
}
}
allprojects {
repositories {
google()
jcenter()
}
}
实际构建配置在buildScript
代码块内,repositories
代码块将JCenter配置成一个仓库,在这种情况下,一个仓库意味着一系列的依赖包,或者说,在我们应用和依赖项目中可使用的一些列可下载函数库。Jcenter是一个很有名的Maven库。
dependencies
代码块用于配置构建过程中的依赖包。这意味着你不能将你的应用或依赖项目所需要的依赖包包含在顶层构建文件中。默认情况下,唯一被定义的依赖包是Gradle的Android插件。每个Android模块都需要有Android插件,因为该插件可使其执行Android相关的任务。
allprojects
代码块可用来声明那些需要被作用于所有模块的属性。你甚至可以在all- project中创建任务,这些任务最终会被运用到所有模块。
3、模块的构建文件:build.gradle
模块层的build.gradle
文件的属性只能应用在Android app模块,它可以覆盖顶层build.gradle
文件的任何属性。该模块的构建文件示例如下:
plugins {
id 'com.android.application'
}
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
defaultConfig {
applicationId "com.example.test1"
minSdkVersion 16
targetSdkVersion 28
versionCode 1
versionName "1.0"
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir:'libs',include:['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0'
}
(1)插件
plugins
:第一行用到了Android应用插件,该插件在顶层构建文件中被配置成了依赖,这个上面说过。谷歌的Android工具团队负责Android插件的编写和维护,并提供构建、测试和打包Android应用以及依赖项目的所有任务。
(2)Android
android
:在构建文件中,占比最大的是android代码块。该代码块包含了全部的Android特有配置,这些特有配置之所以可被使用,是因为之前我们使用了Android插件。
必须有的属性是compileSdkVersion
和buildToolsVersion
。
- 第一个compileSdkVersion:是要用来编译应用的Android API版本
- 第二个buildToolsVersion:是构建工具和编译器使用的版本号。
构建工具包含命令行应用,如aapt、zipalign、dx和renderscript,这些都被用来在打包应用时生成各种中间产物。你可以通过SDK Manager载构建工具。
defaultConfig
代码块用于配置应用的核心属性。此代码块中的属性可覆盖AndroidManifest.xml文件中对应的条目。
applicationId
是这段代码的第一个属性。该属性覆盖了manifest文件中的package name,但applicationId和Package name有一些不同。在Gradle被用作默认的Android构建系统之前,AndroidManifest.xml中的package name有两个用途:作为一个应用的唯一标志,以及在R资源类中被用作包名。使用构建variants, Gradle可更容易地创建不同版本的应用。例如,构建variants可以很容易地构建一个免费版和一个付费版应用。这两个版本需要独立的标识符,这样它们才能在Google Play Store中以不同的应用出现,并且可以同时被安装。然而资源代码和生成的R类,必须在任何时候都保持相同的包名,否则,你的所有源文件都要随着你正在构建的版本而改变。这就是Android工具团队解藕了 package name两种不同用法的原因。定义在manifest文件中的package,继续用在你的源代码和R类中,而之前被用作设备和Google Play唯一标识的package name,现在则被称之为application id。在我们开始尝试不同的构建类型,application id将会变得更加有趣。
在defaultConfig
中,接下来的两个属性是minSdkVersion和targetSdkVersion。这两个属性看起来很熟悉,是因为它们通常作为<users-sdk>标签的一部分,在manifest中被定义。minSdkVersion被用来配置运行应用的最小API级别。targetSdkVersion用于通知系统,该应用已经在某特定Android版本通过测试,从而操作系统不必启用任何向前兼容的行为。这和我们之前看到的complieSdkVersion没有任何关系。
versionCode
和versionName
在manifest文件的作用相同,即为你的应用定义一个版本号和一个版本名称。构建文件中的属性会全面覆盖manifest文件中的属性。因此,如果你在build.gradle中定义了它们,就没有必要在manifest文件中再去定义。如果构建文件不包含某个属性,那么manifest中的该属性就会被用作后备。
buildTypes
代码块可用来定义如何构建和打包不同构建类型的应用。
(3)依赖包
依赖代码块是标准Gradle配置的一部分(这就是其放在android代码块之外的原因),其定义了一个应用或依赖项目的所有依赖包。默认情况下,一个新的Android应用,在libs文件夹下对所有JAR文件构成依赖。根据你在新建项目向导中的选择,其也可能依赖于AppCompat。
4、Daemon(守护进程)
项目启动时,会开启一个client,然后启动一个daemon,通过client向daemon 收发请求,项目关闭,client关闭,daemon保持启动,有类似项目再次部署时,会直接通过新的client访问已经启动的daemon,所以速度很快,默认daemon不使用3小时后关闭;不同项目兼容性考虑,也可以使用 --no-daemon启动项目,就没有速度优势了
手动停止daemon:gradle wrapper --stop
二、Gradle生命周期
Initialization
- Gradle支持单项目和多项目构建。在初始化阶段,Gradle确定哪些项目将参与构建,并为每个项目创建Project实例,一般我们不会接触到它。(比如解析setting.gradle)
Configuration
- 配置阶段,解析每个工程的build.gradle文件,创建要执行的任务子集和确定各种任务之间的关系,并对任务的做一些初始化配置
Execution
- 运行阶段,Gradle根据配置阶段创建和配置的要执行的任务子集,执行任务
三、Gradle任务
1、Task
task是gradle中最小的任务单元,任务之间可以进行复杂的操作(如动态创建任务,多任务间依赖调用等等)。gradle的执行其实就是由各任务组合执行,来对项目进行构建的。
使用gradlew help命令,任何gradle项目都有一个该task,可以执行此命令观察tasks执行的流程是否如预期。
可以使用工具查看,还可以通过gradlew tasks命令查看可运行任务。
- 使用gradlew tasks -all 命令查看所有任务。
- 使用gradlew A B 命令表示执行任务A和任务B,支持驼峰简写
2、自定义任务
在build.gradle中自定义任务:
- task<任务名>{…},在Gradle5.x以上已经删除<<操作符这种写法。
- {…}执行的是配置阶段的代码,执行阶段要处理的逻辑需要调用doFirst,doLast方法,在闭包中实现。doFirst{}表示任务执行开始时调用的方法,doLast{}表示任务执行结束调用的方法。
- task A(dependsOn:[B]){…}表示任务A依赖于任务B,那么B执行在A之前。
- 自定义的任务默认分组到other中
四、Gradle命令行
gradlew -?/-h/-help 使用帮助
gradlew tasks 查看所有可执行Tasks
gradlew – refresh- dependencies assemble 强制刷新依赖
gradlew cBC等价与执行Task cleanBuildCache,这种通过缩写名快速执行任务。
gradlew:app:dependencies 查找app工程依赖树。