Android Gradle的神奇之处 ---- Gradle构建和Task引入

11 篇文章 0 订阅

之前2节,主要是针对Groovy的语法进行了讲解,在Gradle脚本的编写中就会涉及这些语言特性,如果想要编写脚本,自定义Gradle插件,首先需要了解Gradle的构建过程。

Gradle构建和Task引入

1 Gradle工程层级结构

在这里插入图片描述
一个Gradle工程,不管是Android还是其他的工程,只要设计到Gradle,工程结果都是一样的

1 setting.gradle

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
        jcenter() // Warning: this repository is going to shut down soon
        maven {url 'https://jitpack.io'}

        flatDir {
            dirs 'app/libs'
        }
    }
}
rootProject.name = "Diandu" //当前Android主工程名 在
include ':app'

Gradle工程的根,Gradle编译时就是从setting.gradle开始解析,在初始化的时候会生成Setting对象,rootProject就是Setting中的getRootProject(),默认生成了get和set方法

ProjectDescriptor getRootProject();

Gradle是支持多工程构建的,在setting.gradle中可以配置子模块,使用include表示当前为一个子Moudle,每个模块名称前的 " : "代表是跟setting同级的模块

如果在lib文件夹下,有一个lib模块,就可以使用下面的方式拼接

include ':lib:mylib'

如果要引用当前工程之外的一个工程,做工程之间的相互依赖,可以配置依赖的moudle的路径

project(':MyApplication').projectDir = new File('../MyApplication')

2 gradlew.bat

gradle执行的脚本命令,可通过命令行运行gradle脚本

3 build.gradle

当seeting.gradle解析完成之后,就执行 build.gradle脚本,用于生成Project对象,task任务也是在这个阶段完成了配置

buildscript {
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath "com.android.tools.build:gradle:7.0.3"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.20"
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

buildscript中的repositories为构建脚本依赖项添加仓库,也就是dependencies中的插件,像Android的gradle插件,Kotlin的gradle插件等

4 gradle-wrapper.properties

distributionBase=GRADLE_USER_HOME
distributionUrl=https://services.gradle.org/distributions/gradle-7.0.2-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME

用于为不同的设备统一版本,像distributionUrl中声明的gradle版本,在不同设备中,都会下载这个版本的gradle,其中gradle-7.0.2-bin.zip是二进制的发布版本,如果想要看gradle的源码,可以换成gradle-7.0.2-all.zip,其中就包含了gradle的源码

2 Gradle的生命周期

像Activity、Fragment一样,gradle也有自己的生命周期,可用于在编译阶段做对应的调度
在这里插入图片描述

2.1 初始化阶段

在初始化阶段,会执行setting.gradle脚本,是所有脚本执行的起始位置,在这个阶段,gradle会确定哪些模块会参与构建

其中在初始化阶段,有2个钩子函数,settingsEvaluated和projectsLoaded

gradle.settingsEvaluated {

    println "settingsEvaluated"
}

gradle.projectsLoaded {

    println "projectsLoaded"
}

gradle编译执行:

settingsEvaluated
projectsLoaded

> Configure project :
beforeProject

> Configure project :app
beforeProject
组件化

在初始化阶段,Configure之前,如果想要做处理,因为这个时候,project对象还没有生成,只能使用gradle,可以看出在配置阶段之前,这个两个钩子函数中的配置执行了

2.2 配置阶段

在配置阶段,会解析每个项目的build.gradle,生成project对象,同时会配置task但不会执行;

在配置阶段,钩子函数更多,除了gradle的钩子函数之外,还有Project的钩子函数

//对其全部子工程有效
gradle.beforeProject {
    println 'gradle beforeProject'
}
//对当前工程有效
project.afterEvaluate {
    println 'project afterEvaluate'
}

其中,gradle是对其全部子项目有效,对当前工程是无效的;而project只对当前工程有效,而对其子项目是无效的,因此可以使用gradle或者project按需配置工程

> Configure project :
task A Configure
project afterEvaluate

> Configure project :app
gradle beforeProject
组件化

> Configure project :business
gradle beforeProject

这里需要注意一点,如果要对全部的子工程配置,只能在根工程的build.gradle中进行脚本配置;

2.3 执行阶段

在这个阶段,就会真正地执行task任务,那么下面就开始介绍gradle中的task任务

3 Task任务

gradle中的task任务,其实在整个项目创建之后,在build.gradle中就有一个task

task clean(type: Delete) {
    delete rootProject.buildDir
}

这个是一个清除任务,将build文件夹清除,然后重新编译后的生成新的build文件夹

3.1 task基础

创建一个A任务

task A{
}

在Android Studio右侧的Task任务栏中,other文件夹下,就有这个A任务,直接双击就可以执行这个A任务
在这里插入图片描述

task A{

    println "task A"
}

task B{

    println 'task B'
}

task C(dependsOn:[A,B]){

    println 'task C'
}

在Task中,任务的排序是按照首字母的顺序,如果C任务依赖任务A和任务B,那么可以使用dependsOn属性声明

3.1.1 任务的执行顺序

默认情况下,就是按照任务首字母的顺序执行,像C依赖A和B,必须要等到A和B执行完成之后,才可以执行C;如果想要B先执行,那么可以通过mustRunAfter,来设置B先执行,然后A后执行

A.mustRunAfter B

> Task :B UP-TO-DATE
> Task :A
> Task :C

但是如果存在依赖关系,想要B在C之后执行显然是不可能的!

还有一个API是shouldRunAfter,这种就不是强制性的,不一定A是在B之后执行

3.1.2 doFirst doLast

在配置阶段,是不会执行task中的action的,只有在执行阶段才会执行,那么doFirst和doLast就是Action方法

C.doFirst {
    println "C do First"
}

C.doLast {
    println "C do doLast"
}

A.doFirst {
    println "A do First"
}

任务执行输出:

> Task :A
A do First

> Task :C
C do First
C do doLast

3.1.3 资源回收

当一个任务执行完成之后,需要对无用资源回收,可以使用finalizedBy

task finalizeTask{
    println '资源回收'
}

A.finalizedBy finalizeTask


> Task :B UP-TO-DATE
> Task :A
A do First
> Task :finalizeTask UP-TO-DATE
> Task :C
C do First
C do doLast

我们可以看到当任务A执行完成之后,立刻执行了资源回收任务

3.2 自定义Task

打印每个Task的class,发现每个Task都是DefaultTask类型,自定义Task也是以DefaultTask为基类

class org.gradle.api.DefaultTask_Decorated


class MyTask extends DefaultTask{

    MyTask(){
        group 'custome'
        println 'MyTask 构造方法 配置阶段执行'
    }

    @TaskAction
    def Action(){

        println 'MyTask 执行了'
    }
}

tasks.create('MyTask',MyTask){
    //执行Action中的方法
    it.Action()
}

自定义Task继承自DefaultTask,在构造方法中可以做初始化,这部分是在配置阶段完成的,之前讲到自己创建的task默认是放在other分组中,如果想单独放在一个分组中,可以使用group分组
在这里插入图片描述

3.2.1 自定义Task的创建方式1 — tasks.create

使用tasks.create可以创建自定义的task任务,第一个参数为创建的Task名称,
第二个参数为Task任务的类型,即自定义的任务,在闭包当中可以调用自定义Task中的TaskAction方法

3.2.2 自定义Task的创建方式2 ---- task

task customTask(type: MyTask){
    Action()
}

这种方式才是主流的创建方式,类似于build.gradle中的清除任务,通过type声明任务的类型,可以直接调用MyTask中的TaskAction方法

> Task :customTask
MyTask 执行了

task是Project中的task,因此每个脚本的执行都必须依赖Project对象,因此在创建一个build.gradle文件之后,这个脚本是不能单独运行的,因为它没有被解析生成对应的Project对象,必须通过apply from 依赖到某个build.gradle中

总结

写到这里也结束了,在文章最后放上一个小小的福利,以下为小编自己在学习过程中整理出的一个关于 java开发 的学习思路及方向。从事互联网开发,最主要的是要学好技术,而学习技术是一条慢长而艰苦的道路,不能靠一时激情,也不是熬几天几夜就能学好的,必须养成平时努力学习的习惯,更加需要准确的学习方向达到有效的学习效果。

由于内容较多就只放上一个大概的大纲,需要更及详细的学习思维导图的 点击我的Gitee获取
还有 高级java全套视频教程 java进阶架构师 视频+资料+代码+面试题!

全方面的java进阶实践技术资料,并且还有技术大牛一起讨论交流解决问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值