Gradle中的主要对象

来源:互联网 发布:java模糊查询 编辑:程序博客网 时间:2024/06/14 04:28

我们接触Gradle的时候,大都是了解build.gradle里面怎么配置,比如我们很常见的一行代码 apply plugin: ‘com.android.application’,我们知道这么配,并且IDE已经生成好了,可能你都不用关心,却不知道这其实是函数调用,有相关的API。 那么这段代码是什么意思呢?这其实就是调用了project对象的apply方法,传入了一个以plugin为key的map。完整写出来就是这样的:project.apply([plugin: ‘com.android.application’])。这样就明白了。所以我们要真正掌握Gradle,必须要学习Gradle的API。

Gradle 执行的时候和 Groovy 一样,会把脚本转换成 Java 对象,Gradle 主要有三种对象,这三种对象对应三种不同的脚本文件,在 gradle 执行的时候,会将脚本转换成对应的对端:

这里写图片描述

  • Settings对象:每个settings.gradle会转换成一个Settings对象。

  • Project对象:每个build.gradle会转换成一个Project对象。

  • Gradle对象:构建初始化时创建,整个构建执行过程中只有这么一个对象,一般很少去修改这个默认配置脚本。

Gradle生命周期

Gradle构建系统有自己的生命周期,初始化、配置和运行三个阶段。

1.初始化阶段,会去读取根工程中setting.gradle中的include信息,决定有哪几个工程加入构建,比如下面有三个工程: include ‘:app’, ‘:lib1’, ‘:lib2

2.配置阶段,解析每个project中的build.gradle脚本,配置project对象,一个对象由多个任务组成,此阶段也会去创建、配置task及相关信息。配置阶段完成后,整个build的project以及内部的Task关系就确定了。

3.运行阶段,根据gradle命令传递过来的task名称,执行相关依赖任务

这里写图片描述

Gradle对象

初始化脚本Init script(Gradle)类似于Gradle的其他类型脚本,这种脚本在构建开始之前运行,主要的用途是为接下来的Build script做一些准备工作。我们如果需要编写初始化脚本Init script,则可以把它按规则放置在USER_HOME/.gradle/相关目录下。

Gradle对象的API

//在settings.gradle中,则输出"In settings,gradle id is"  println "In posdevice, gradle id is " +gradle.hashCode()  println "Home Dir:" + gradle.gradleHomeDir  println "User Home Dir:" + gradle.gradleUserHomeDir  println "Parent: " + gradle.parent
gradle.buildFinished {    print("build is finished")}

gradle整个编译过程都是可控的,通过实现TaskExecutionListener和BuildListener可以对整个编译过程进行监听。下面的代码打印了一下task的名字。

gradle.addListener(new LifecycleListener())class LifecycleListener implements  TaskExecutionListener,BuildListener{    @Override    void buildStarted(Gradle gradle) {    }    @Override    void settingsEvaluated(Settings settings) {    }    @Override    void projectsLoaded(Gradle gradle) {    }    @Override    void projectsEvaluated(Gradle gradle) {    }    @Override    void buildFinished(BuildResult result) {    }    @Override    void beforeExecute(Task task) {        println("beforeExecute "+task.name)    }    @Override    void afterExecute(Task task, TaskState state) {        println("afterExecute  name="+task.name+" state="+state.toString() )    }}

Project对象

每一个build.gradle文件都会转换成一个Project对象。Project包含若干Tasks。一个项目在构建时都具备如下流程:

  • 为当前项目创建一个Settings类型的实例。

  • 如果当前项目存在settings.gradle文件,则通过该文件配置刚才创建的Settings实例。

  • 通过Settings实例的配置创建项目层级结构的Project对象实例。

  • 最后通过上面创建的项目层级结构Project对象实例去执行每个Project对应的build.gradle脚本。

另外,由于Project对应具体的工程,所以需要为Project加载所需要的插件,比如为Java工程加载Java插件。其实,一个Project包含多少Task往往是插件决定的。

1、加载插件

Project的API位于https://docs.gradle.org/current/javadoc/org/gradle/api/Project.html。加载插件是调用它的apply函数.apply其实是Project实现的PluginAware接口定义的:

这里写图片描述

加载插件的方式:

apply plugin: 'com.android.library'    <==如果是编译Library,则加载此插件  apply plugin: 'com.android.application'  <==如果是编译Android APP,则加载此插件 

apply是一个函数,此处调用的是上图中最后一个apply函数。注意,Groovy支持函数调用的时候通过 参数名1:参数值2,参数名2:参数值2 的方式来传递参数

除了加载二进制的插件(上面的插件其实都是下载了对应的jar包,这也是通常意义上我们所理解的插件),还可以加载一个gradle文件。为什么要加载gradle文件呢?

其实这和代码的模块划分有关。一般而言,我会把一些通用的函数放到一个名叫utils.gradle文件里。然后在其他工程的build.gradle来加载这utils.gradle。这样,通过一些处理,我就可以调用utils.gradle中定义的函数了。

加载utils.gradle插件的代码如下:

apply from: rootProject.getRootDir().getAbsolutePath() + "/utils.gradle"  

utils.gradle是我封装的一个gradle脚本,里边定义了一些方便函数,比如读取AndroidManifest.xml中的versionName,或者是copy jar包/APK包到指定的目录

这里也是使用apply的最后一个函数。那么,apply最后一个函数到底支持哪些参数呢?API会告诉你。
这里写图片描述

2、Task介绍

Task是Gradle中的一种数据类型,它代表了一些要执行或者要干的工作。不同的插件可以添加不同的Task。每一个Task都需要和一个Project关联。
Task的API文档位于https://docs.gradle.org/current/dsl/org.gradle.api.Task.html。关于Task,我这里简单介绍下build.gradle中怎么写它,以及Task中一些常见的类型
关于Task。来看下面的例子:

/Task是和Project关联的,所以,我们要利用Project的task函数来创建一个Task  task myTask  <==myTask是新建Task的名字  task myTask { configure closure }  task myType << { task action } <==注意,<<符号是doLast的缩写  task myTask(type: SomeType)  task myTask(type: SomeType) { configure closure }  

上述代码中都用了Project的一个函数,名为task。请移步这里。

项目构建过程中那么多任务,有些test相关的任务可能根本不需要,可以直接关掉,在build.gradle中加入如下脚本:

tasks.whenTaskAdded { task ->    if (task.name.contains('AndroidTest')) {        task.enabled = false    }}

3、设置属性

如果是单个脚本,则不需要考虑属性的跨脚本传播,但是Gradle往往包含不止一个build.gradle文件,比如我设置的utils.gradle,settings.gradle。如何在多个脚本中设置属性呢?
Gradle提供了一种名为extra property的方法。extra property是额外属性的意思,在第一次定义该属性的时候需要通过ext前缀来标示它是一个额外的属性。定义好之后,后面的存取就不需要ext前缀了。ext属性支持Project和Gradle对象。即Project和Gradle对象都可以设置ext属性
举个例子:
我在build.gradle中想为Gradle对象设置一些外置属性,所以在initMinshengGradleEnvironment函数中

def initMinshengGradleEnvironment(){      //属性值从local.properites中读取      Properties properties = new Properties()      File propertyFile = new File(rootDir.getAbsolutePath() +"/local.properties")     properties.load(propertyFile.newDataInputStream())      //gradle就是gradle对象。它默认是Settings和Project的成员变量。可直接获取     //ext前缀,表明操作的是外置属性。api是一个新的属性名。前面说过,只在     //第一次定义或者设置它的时候需要ext前缀      gradle.ext.api =properties.getProperty('sdk.api')      println gradle.api  //再次存取api的时候,就不需要ext前缀了      ......      }

参考文章:http://blog.csdn.net/innost/article/details/48228651