Adnroid Studio - Gradle

一、概念

项目自动化构建管理,可以使用 Groovy DSL 语言(文件后缀xxx.gradle)或 Kotlin DSL 语言(文件后缀 xxx.gradle.kts)编写。

二、全局设置 settings.gradle

是整个 Gradle 项目构建的入口点,这里配置的都是全局的。构件时会生成一个 Settings 对象,这些简短的 DSL 语法底层都是在该对象上进行调用的。

Settings对象常用属性及方法说明
buildCache缓存配置。
plugins声明使用到的插件(全局)。
rootDir根目录。
rootProject根项目(该工程)。
settings返回构建时通过该文件实例化出的 Settings 对象。
include()将子模块添加到构建列表中(传入名称)。
includeBuild()将其它 Gradle 工程添加到构建列表中(传入路径)。

2.1 配置插件和依赖的仓库地址

内置的仓库能函数直接调用,自定义的要用 maven() 来指定地址。

// 插件管理
pluginManagement {
    // 仓库列表
    repositories {
        // 指定地址
        // 阿里云镜像仓库加速访问
        maven("https://maven.aliyun.com/repository/gradle-plugin")
        maven("https://maven.aliyun.com/repository/public")
        maven("https://maven.aliyun.com/repository/central")
        maven("https://maven.aliyun.com/repository/apache-snapshots")
        maven("https://maven.aliyun.com/repository/google")
        // Google插件仓库
        google {
            content {
                includeGroupByRegex("com\\.android.*")
                includeGroupByRegex("com\\.google.*")
                includeGroupByRegex("androidx.*")
            }
        }
        // Maven中心仓库
        mavenCentral()
        // Gradle插件仓库
        gradlePluginPortal()
    }
}

// 依赖解析管理(更推荐在 build.gradle 文件中配置)
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        maven("https://maven.aliyun.com/repository/gradle-plugin")
        maven("https://maven.aliyun.com/repository/public")
        maven("https://maven.aliyun.com/repository/central")
        maven("https://maven.aliyun.com/repository/apache-snapshots")
        maven("https://maven.aliyun.com/repository/google")
        google()
        mavenCentral()
    }
}

2.2 配置插件

Gradle 插件可以帮助我们在构建过程中实现各种各样的高级功能,用于扩展任务(tasks)或构建逻辑。

plugins {
    id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0"
}

2.3 添加子模块

让子模块参与到构建中。构件时会先读取 Settings.gradle,根据声明再去读取子模块中的 build.gradle 文件)。

// rootProject 代表工程,name 属性是其名称
rootProject.name = "Demo"
// 添加子模块,没有子模块可以不写
include("base")

三、模块配置 build.gradle

针对构建进行配置。对于 Settings.gradle 中声明的子模块,Gradle 都会为其生成一个 Project 对象,这些简短的 DSL 语法底层都是在该对象上进行调用的。

Project对象常用属性及方法说明
name模块名称。
path模块路径。
description模块描述。
dependencies配置模块的依赖列表。
repositories配置模块的依赖仓库。
layout通过此对象访问模块的关键位置。
group模块的组。
version模块的版本。

3.1 配置插件

// 指定项目需要使用到的插件
plugins {
    id("org.jetbrains.kotlin.jvk") version "1.9.0"    // 普通方式
    alias(libs.plugins.android.application) apply false    // toml方式
}

3.2 配置依赖

普通方法仅用于当前模块,带有 api 版本的方法可向上传递(引入这个模块的上层模块不用重复添加依赖项)。

DependencyHandlerScope的方法说明

implementation

api

添加依赖。
compileOnly仅在编译时可用,不会包含在最终构建结果中(编译完不会一起打包)。
runtimeOnly仅在运行时使用,不用于编译。如 MySQL 驱动不需要在项目编程时使用,但在程序运行时需要用到。

testImplementation

testApi

测试时需要的依赖。

androidTestImplementation

androidTestApi

Android测试时需要的依赖。

debugImplementation

debugApi

debug时需要的依赖。
kapt用于添加 Kotlin 注解处理器依赖项
annotationProcessor用于添加 Java 朱家琪依赖项。

3.2.1 添加

dependencies {
    // 引入仓库中的依赖
    implementation("io.coil-kt.coil3:coil-compose:3.5.0")    // 普通方式
    implementation(libs.compose.material3)    // 通过 toml 的方式
    // 导入本地jar包(存放在根目录的lib里)
    // 需要一个包一个包写
    implementation(
        files(
            "lib/spring-context-6.1.3.jar",
            "lib/spring-core-6.1.3.jar"
        )
    )
    // 直接给目录
    implementation(fileTree("lib"))
}

3.2.2 排除、强制(解决冲突)

一个依赖里会有前置依赖(该依赖还依赖别的),有时会有冲突,可以排除该依赖中的前置依赖。

implementation("org.springframework:string-context:6.1.3") {
    exclude("org.springframework")    // 排除整个组
    exclude("org.springframework:spring-aop")    // 排除具体某一个某块
}

spring-context 中包含了 spring-aop,当添加了 context 6.1.3 又添加了 aop 6.1.1 会优先使用更新的 aop 6.1.3。 此时可以通过排除不用最新的,也可以添加感叹号强制使用旧的。

// 两种方式二选一
implementation("org.springframework:string-context:6.1.3") {
    exclude("org.springframework:spring-aop")    // 不用新的
}
implementation("org.springframework:string-aop:6.1.1!!")    // 双感叹号强制使用

四、自定义任务 Task

Gradle 的工作由一个或多个任务(Task)来定义,任务代表构建执行的独立工作单元,比如编译一些类、创建 jar 包、生成 JavaDoc 文档、将一些内容发布到代码仓库。这些任务由插件提供(最直观的感受就是那些用来配置的DSL语句,以及build后显示的各种Task信息),工程中引入插件后就可以执行对应的任务了。当然也可以在 build.gradle 中创建自定义任务。

4.1 创建任务

register()懒加载,用到时才创建。
create()普通创建。

 IDE 代码左边可以点击箭头执行,也可以终端输入 ./gradle hello 执行。

// 第一个参数为任务名称,第二个参数 Lambda 为具体操作
tasks.register("hello") {
    // 设置组(相同组名的任务会在IDE的Gradle面板里聚合显示)
    group = ""
    // 设置描述信息(终端输入 ./gradle tasks 会显示可用任务和描述)
    description = ""
    println("执行中")
    // 插入到队列头部
    doFirst {
        println("任务开始")
    }
    // 插入到队列尾部
    doLast {
        println("任务结束")
    }
}

4.2 默认任务

defaultTasks()要传入已有任务名,终端输入 ./gradle 就会执行。
defaultTsks("hello")    // 默认任务,传入已有任务名

4.3 前置任务

一个任务还可以依赖其它任务。

tasks.register("hello") {
    // 执行自定义任务之前,需要先完成源代码编译
    dependsOn(tasks.compileJava)    // 也可以传任务名字符串
}

4.4 修改任务

named()修改已有任务。
// 执行build前先执行我们的自定义任务
tasks.named("build") {
    dependsOn("hello")
}

// 直接从tasks中获取build任务(仅限插件提供的任务)
tasks.build {
    dependsOn("hello")
}

4.5 内置任务类型

上述提到的方法默认泛型都是<Task>类型,还可以指定为其它内置类型:Zip、Jar、Sign、Delete 等。

tasks.register<Copy>("hello") {
    from("build/classes")    // 复制的目录
    into("test")             // 目标位置
    dependsOn("tasks.build")    // 依赖一下前置任务
}

4.6 自定义任务类型

通过继承 DefaultTask 类来创建自定义任务类型,自定义的这个类必须可继承(要么open要么abstract)。

// 自定义
open class HelloTask : DefaultTask() {
    private var name: String = ""
    // 注解声明的函数才会在任务执行时被自动调用
    @TaskAction
    fun hello() { println("名字是:$name") }
    // 也可以声明普通函数
    fun setName(str: String) { name = str }
}

// 使用(运行会执行 HelloTask 中的 hello() 函数)
tasks.register<HelloTask>("hello") {
    // 此时 this 就是 HelloTask 类型了
    setName("张三")    // 调用普通函数
}

五、生命周期钩子

可以在不同阶段执行自定义内容,如统计某一阶段或某个任务的耗时。

未特别说明的,在 settings.gradle 或 build.gradle 中都可以调用。

初始阶段gradle.settingsEvaluated()完成工程的配置阶段之后调用(只能定义在 setting.gradle 或 init.gradle 中)。
gradle.projectsLoaded()所有模块加载之后调用(只能定义在 setting.gradle 或 init.gradle 中)。
配置阶段gradle.beforeProject()每个模块完成配置之前调用(只能定义在 setting.gradle 或 init.gradle 中)。
gradle.afterProject()每个模块配置完成之后调用。
gradle.projectsEvaluated()所有模块配置完成之后调用。
gradle.aftersEvaluated()整个配置阶段完成后调用。
gradle.taskGraph.whenReady()全部任务都已经构建完成时调用。
执行阶段gradle.taskGraph.beforeTask()每个任务执行前调用。
gradle.taskGraph.afterTask()每个任务执行后调用。
gradle.buildFinished()整个构建全部结束后调用
gradle.settingsEvaluated {
    println("开始构建")
}

gradle.buildFinished {
    println("结束构建")
}

统计每个任务的耗时:

var time = 0L
gradle.taskGraph.beforeTask {
    time = System.currentTimeMillis()
}
gradle.taskGraph.afterTask {
    val takeTime = System.currentTimeMillis - time
    println("任务$name 耗时:$takeTime")
}

六、多模块

6.1 依赖其它模块

implemention(project(":module_base"))

6.2 统一配置

对多个模块进行统一配置,可以在根目录创建一个 build.gradle 来编写。

// 表示对所有子模块生效(用allprojects包括自己也生效)
subprojects {
    // 定义插件,plugin()在这里不行了
    apply(plugin = "java")
    // 定义组
    group = ""
    // 定义版本
    version = ""
    // 定义仓库地址
    repositories {
        maven("https://maven.aliyun.com/repository/public")
    }
}

6.3 依赖传递

A模块依赖B模块,可以调用B模块中的功能,C依赖A模块却不能调用B中的功能,就因为中间隔了一层。解决方法是将 implemention 改成 api ,参见上面 3.2。

6.4 buildSrc 模块

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值