我是靠谱客的博主 害怕哑铃,最近开发中收集的这篇文章主要介绍Android Gradle的神奇之处 ---- Gradle构建和Task引入1 Gradle工程层级结构2 Gradle的生命周期3 Task任务,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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

Gradle构建和Task引入

  • 1 Gradle工程层级结构
  • 2 Gradle的生命周期
    • 2.1 初始化阶段
    • 2.2 配置阶段
    • 2.3 执行阶段
  • 3 Task任务
    • 3.1 task基础
      • 3.1.1 任务的执行顺序
      • 3.1.2 doFirst doLast
      • 3.1.3 资源回收
    • 3.2 自定义Task
      • 3.2.1 自定义Task的创建方式1 --- tasks.create
      • 3.2.2 自定义Task的创建方式2 ---- 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中

最后

以上就是害怕哑铃为你收集整理的Android Gradle的神奇之处 ---- Gradle构建和Task引入1 Gradle工程层级结构2 Gradle的生命周期3 Task任务的全部内容,希望文章能够帮你解决Android Gradle的神奇之处 ---- Gradle构建和Task引入1 Gradle工程层级结构2 Gradle的生命周期3 Task任务所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(35)

评论列表共有 0 条评论

立即
投稿
返回
顶部