DSL介绍:全称domain specific language 领域特定语言
核心思想:求专不求全,解决特定问题
APK构建流程
- 编译资源+编译代码
- 压缩包
- 签名
- 对齐
一、groovy语法
Gradle注释:
//单行住宿
/*
多行注释
*/
Gradle支持的类型:
byte、short、int、long、float、double、char、String
int a = 10
int b = 20
println("a = $a")
println("b = $b")
//字符串
String str = "Hello, World"
String str2 = str.toUpperCase()
println("str is $str2")
//列表
def array = [1, 2, 3, 4]
array.add(5)
println("array is $array")
array.forEach {
println("each item is $it")
}
//映射表
def map = ["name": "pujh", "age": "25"]
println("age is ${map["age"]}")
//循环
for (int i = 0; i < 10; i++) {
if (i > 5) {
println("i is $i")
}
}
//函数
def hello(String name){
println("hello $name")
}
hello("pujh")
groovy闭包
- 开放匿名的代码块,可以接受参数,具有返回值,也可以被分配给变量
- 定义规则:
{[params->] staements}
//无参闭包
def c = { println("Hello Closure") }
c()
//有一个参数的时候,参数可以忽略,默认名称为it
def c2 = { println("c2: it = $it") }
c2("idste")
//只有一个参数的时候,名称可以任意指定,但是it就不能用了
def c3 = { name -> println("c2: it = $name") }
c3("idste")
def myAndroid = {
compileSdkVersion 27
defaultConfig {
versionName "1.0"
}
}
Android a = new Android()
//将闭包与具体对象关联起来
myAndroid.delegate = a
myAndroid.call()
println("myAndroid = $a")
class DefaultConfig {
private String versionName
def versionName(String versionName) {
this.versionName = versionName
}
@Override
String toString() {
return "DefaultConfig{ versionName = $versionName }"
}
}
class Android {
private int compileSdkVersion;
private DefaultConfig defaultConfig;
Android() {
defaultConfig = new DefaultConfig()
}
def compileSdkVersion(int compileSdkVersion) {
this.compileSdkVersion = compileSdkVersion;
}
def defaultConfig(Closure closure) {
//将闭包与具体对象关联起来
closure.setDelegate(defaultConfig)
closure.call()
}
@Override
String toString() {
return "Android{ compileSdkVersion = $compileSdkVersion, defaultConfig = $defaultConfig }"
}
}
二、Gradle基础
1、gradle命令行
gradle命令行的执行格式:
./gradlew [task-name...][-option-name]
执行任务:
./gradlew clean -q
查看所有子工程:
./gradlew projects
查看所有任务:
./gradlew tasks
Gradle升级:
./gradlew wrapper --gradle-version 8.3
2、gradle文件结构
- settings.gradle
- build.gradle
- gradle.properties
3、gradle生命周期
Gradle构建的3个阶段
- 1、初始化阶段:解析整个工程中所有的Project,构建所有的Project对应的project对象
- 2、定义配置阶段:解析所有project对象中的task,构建好所有task的拓扑图
- 3、执行阶段:执行具体的task及其依赖task
在2、3阶段中间执行的回调代码afterEvaluate
- settings.gradle.kts
println("[lifecycle] 我是settings.gradle, rootProject路径是:${rootProject.projectDir}")
//添加 构建生命周期 监听
gradle.addBuildListener(object : BuildAdapter() {
override fun settingsEvaluated(settings: Settings) {
println("[lifecycle] 初始化阶段完成")
}
override fun projectsEvaluated(gradle: Gradle) {
println("[lifecycle] 配置阶段完成")
gradle.rootProject.childProjects.forEach { (name, project) ->
println("[子工程] $name, 路径是:${project.projectDir}")
}
}
override fun buildFinished(result: BuildResult) {
println("[lifecycle] 构建结束")
}
})
- build.gradle.kts
println("[lifecycle] 我是根目录的build.gradle")
- app/build.gradle.kts
println("[lifecycle] 我是app的build.gradle")
task("testTask") {
doLast {
println("我是 testTask任务")
}
}
执行结果: .\gradlew testTask -q
[lifecycle] 我是settings.gradle, rootProject路径是:C:\Users\iDste-PC\Desktop\Gradle
[lifecycle] 初始化阶段完成
[lifecycle] 我是根目录build.gradle
[lifecycle] 我是app build.gradle
[lifecycle] 配置阶段完成
[子工程] app, 路径是:C:\Users\iDste-PC\Desktop\Gradle\app
我是 testTask任务
[lifecycle] 构建结束
几个主要角色
- 初始化阶段:root project
root project是一个ProjectDescriptor接口,可以通过接口获取根工程的名称、目录
- 配置阶段:project
在配置阶段就可以拿到project对象
- 执行阶段:task
三、gradle任务
task("testTask") {
doLast {
println("我是 testTask任务")
}
}
task("test2") {
dependsOn.add("testTask")
doLast {
println("我是 test2 任务")
}
}
实现参数配置
- 定义Extension
- 注册Extension
- 使用Extension
- 获取Extension
查看模块依赖项
想要查看整个项目的依赖传递关系,使用命令
gradlew app:dependencies --configuration releaseRuntimeClasspath
x.x.x() 该依赖已经有了,将不再重复依赖 x.x.x->x.x.x 该依赖的版本被箭头所指的版本代替 x.x.x->x.x.x() 该依赖的版本被箭头所指的版本代替,并且该依赖已经有了,将不再重复依赖
configurations {
// all {
// resolutionStrategy {
// force("androidx.appcompat:appcompat:1.1.0")
// }
// exclude()
// }
create("myConfiguration") {
println("PUJH myConfiguration")
}
}
val copyTask = task("copyTask", Copy::class) {
from(configurations)
into("allLibs")
}
dependencies {
val test = configurations.getByName("myConfiguration")
test(libs.androidx.core.ktx)
// implementation(libs.androidx.core.ktx) {
// isTransitive = false //返回true包括传递的依赖,返回false排除传递的依赖
// exclude(group = "", module = "")
// force = true
// }
}
Gradle插件
- 提供具体的构建功能(Task)
- 提高代码的可复用性
1、build script脚本
把插件写在build.gradle文件中,一般用于简单的逻辑,只在该build.gradle文件可见
//build.gradle.kts
class GreetingPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.task("hello") {
doLast {
println("Hello from the GreetingPlugin")
}
}
}
}
//直接依赖build script插件
apply<GreetingPlugin>()
当然也可以将上述内容写在单独的一个gradle文件中,如other.gradle.kts,然后通过apply引入
//build.gradle.kts
//引入单独的gradle脚本文件
apply(from = "other.gradle.kts")
2、buildSrc目录
buildSrc是一个特殊的工程名称,当根工程中出现一个名为buildSrc的子工程时,gradle会将其作为一个gradle插件工程。并且该工程的插件可以被其余工程进行引用。
在buildSrc中创建插件有2种方式:脚本插件和二进制插件
2.1、脚本插件
顾名思义,就是将插件的代码写在脚本文件中,比如groovy脚本文件或gradle.kts脚本文件。并且该脚本文件需要存放在buildSrc/src/main/java/中,脚本文件名的路径名+文件名会作为这个插件的id。
比如插件脚本文件:
buildSrc/src/main/java/com/test/scripts/GreetingPlugin.gradle.kts
内容如下:
package com.test.scripts
tasks.register("BuildSrcHello") {
group = "pujh"
doLast {
println("Hello from the BuildSrc")
}
}
在项目module中,通过以下命令进行依赖
//:app build.gradle.kts
apply(plugin = "com.test.scripts.GreetingPlugin")
//或者
plugins {
id("com.test.scripts.GreetingPlugin")
}
2.2、二进制插件
二进制插件,要求我们插件定义在一个普通的代码文件中,如java、groovy、kt文件。并且要在buildSrc/mian/resources/META-INF/gradle-plugins/中创建一个properties文件,其文件名会作为这个插件的id,文件内容包含implementation-class字段,指向具体的插件类:如:
文件名:com.test.hello.properties
implementation-class=com.test.HelloPlugin
插件代码:
//com.test.HelloPlugin.kt
class HelloPlugin : Plugin<Project> {
override fun apply(target: Project) {
println("com.test.plugin")
}
}
使用插件时,通过以下方式引入:
//:app build.gradle.kts
apply(plugin = "com.test.hello")
//或者
plugins {
id("com.test.hello")
}
3、独立项目
一个独立的java项目/模块,可以将文件包发布到仓库中,然后让其余项目进行依赖。
我们创建一个名为plugins的java/kotlin模块,并在settings.gradle.kts将include修改为includeBuild。
rootProject.name = "Gradle"
include(":app")
//include(":plugins")
includeBuild("plugins") //注意这里没有冒号
此时plugins将会变成一个独立的插件工程,但此时工程中还没有任何插件,我们需要先修改工程中的build.gradle.kts
buildscript {
repositories {
google()
gradlePluginPortal()
}
dependencies {
classpath(kotlin("gradle-plugin", "1.9.23"))
}
}
plugins {
`kotlin-dsl`
`java-gradle-plugin`
`maven-publish`
}
repositories {
google()
gradlePluginPortal()
}
dependencies {
implementation(gradleKotlinDsl())
implementation("com.android.tools.build:gradle:8.4.1")
}
gradlePlugin {
plugins {
create("myplugin") {
group = "com.test"
id = "myplugin"
implementationClass = "com.test.plugin.MyPlugin"
version = "1.0"
}
}
}
publishing {
repositories {
maven(url = "../repo")
}
}
//com.test.plugin.MyPlugin.kt
class MyPlugin : Plugin<Project> {
override fun apply(target: Project) {
println("com.test.plugin.MyPlugin")
}
}
Transform
Transform在Gradle8.0中被移除