Gradle简单介绍

gradle在Android studio中和project的关系

打开Android studio窗口,一般是一个工程下面有一个主module,和其他相关的依赖module,但是对于gradle来说,其实每一个module都是一个project,每个project下面都需要有一个buid.gradle,即是该project的编译脚本,但是如果针对每一个project都单独编译的话, 想必是个很耗时的工作,而且大多数情况下,各个project 之间也是相互依赖的,所以gradle定义了muti-project build,即是一个project可以连带其附属的子project一起编译,只要在该project目录下建立一个setting.gradle,然后将所有的project在其中include进来即可,同时也可以在项目根目录下建立一个build.grale,配置一些各个project都可以用到的配置信息,这个是非必要的,但是如果要支持mutl-project build,那么必须要有setting.gradle:例如:

include ':app',':securitySdk',':networkSdk'

同时可以在settin.gralde中定义一些函数,执行一些必要工作,例如:

include ':app', ':JavaLibrary'

def initSomething(){
    println "initialize something when build"
}

initSomething()

project是有多个Task组成的,当执行gradle project时,其实就是执行project的Task,这些Task会完成相应的工作。

如何查看project下的tasks任务

首先cd 到主工程下,例如工程目录如下:

在这里插入图片描述

想要查看app下的task,执行:gradle app,既可以看到:

在这里插入图片描述

当然也可以直观的从Android studio右侧工具栏Gradle中点击查看具体的task,例如:

在这里插入图片描述

gradle task-name执行任务

从上面可以看出,各个task的工作和名称有着极其紧密的联系,所以如果想要直接执行某一个Task,就可以直接的用"gradle tash-name"去执行了,由于gradle是基于Groovy语言的,所以其实执行这些指令就是调用Groovy的函数而已。

Gradle的工作流程

gradle的工作流程如图:

扫描二维码关注公众号,回复: 5796450 查看本文章

在这里插入图片描述

主要分为3步:

  1. 初始化阶段,其实就是执行工程目录下的setting.gradle
  2. Configration 阶段,解析每个project的build.gradle,其内部的任务也会被添加到一个有向图里,用于解决执行过程中的依赖关系,这两个阶段之间,可以加一些定制化的Hook。
  3. 最后就是执行任务阶段,在gradle XXX中指定的任务,gradle就会将这个XXX任务链上的所有任务都按照依赖顺序执行一遍。

gradle API参考链接

gradle执行时,会将脚本转换成Java对象,Gradle主要有3种对象,不同的对象和不同的脚本文件对应:

  • Gradle对象:当执行grade XXX的时候,gradle会从默认的脚本中构建一个gradle对象,整个执行过程,只有一个该对象;
  • Project对象:每个build.gralde都会转换成一个project对象
  • Settings对象:每一个setting.gradle都会转换成一个Settings对象

Project对象

每一个build.gradle文件都会转换成一个Project对象,对应的是Gradle中的Build Script.Project 包含若干 Tasks。另外,由于 Project 对应具体的工程,所以需要为 Project 加载 所需要的插件,比如为 Java 工程加载 Java 插件。其实,一个 Project 包含多少 Task 往往是 插件决定的。
所以,在 Project 中要做的事情:

  • 加载插件;
  • 不同插件有不同的行话,即不同的配置。我们要在 Project 中配置好,这样插 件就知道从哪里读取源文件等
  • 设置属性。

加载插件

加载插件通过调用appply函数,函数调用时通过 参数名1:参数值2, 参数名2:参数值2的方式来传递参数,例如:

apply plugin:'com.android.library'.  //如果是编译library,则加载这个插件
applu plugin:'com.android.application'  //如果是Android app,则加载此插件

上面这些插件其实就是下载了相应的jar包,另外也可以加载gradle文件,例如将一些通用函数放到一个utils.gralde中,然后其他过程的gradle来加载这个utils.gradle,然后就可以调用里面的函数了,例如:

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

apply函数API接口

Task介绍

Task是gradle的一种数据类型,代表了一些要执行或者要干的工作,不同的插件可以添加不同的task,每一个task都需要有一个project关联,具体看下task的例子,在build.gradle中定义:

//Task时和project关联的,所以要利用project的task函数来创建一个Task。
task myTask  //新建task
task myTask{ configure closure} 
task myType << {task action} // <<是doLast的缩写
task myTask(type:SomeType)
task myTask(type:SomeType){configure closure}

说明:
一个 Task 包含若干 Action。所以,Task 有 doFirst 和 doLast 两个函数,用于 添加需要最先执行的 Action 和需要和需要最后执行的 Action。Action 就是一个闭 包。

  • Task 创建的时候可以指定 Type,通过 type:名字表达。这是其实就是告诉 Gradle,这个新建的 Task 对象会从哪个基类 Task 派生。比如,Gradle 本 身提供了一些通用的 Task,最常见的有 Copy 任务。Copy 是 Gradle 中的一个类。当我们:task myTask(type:Copy)的时候,创建的 Task 就是一个 Copy Task。
  • 当我们使用 task myTask{ xxx}的时候。花括号是一个 closure。这会导致 gradle 在创建这个 Task 之后,返回给用户之前,会先执行 closure 的内容。
  • 当我们使用 task myTask << {xxx}的时候,我们创建了一个 Task 对象,同时把 closure 做为一个 action 加到这个 Task 的 action 队列中,并且告诉它“最后才执行这个 closure”(注意,<<符号是 doLast 的代表)。

gradle实例

1.首先创建一个utils.gradle,用于定义一些公共的函数,以便被其他project引用

def getVersionNameAdvanced(){
    def xmlFile = project.file("AndroidManifest.xml")
    def rootManifest = new XmlSlurper().parse(xmlFile)
    return rootManifest['@android:versionName']

}
//对于library的编译,disable所有的debug编译任务
def disableDeugBuild(){
    //project.tasks包含了所有的tasks,findAll就是找到那些名字中带debug的Task,返回值保存到targetTasks容器中
    def targetTasks = project.tasks.findAll {
        task ->
            task.name.contains("Debug")
    }
    //对于满足条件的task,设置它为disable,这样,这个task就不会被执行
    targetTasks.each {
        println "disable debug task :${it.name}"
        it.setEnabled(false)
    }
}
//将函数设置为 extra 属性中去,这样,加载 utils.gradle 的 Project 就能调用此文件中定义的函数了
ext{
    getVersionNameAdavanced = this.&getVersionNameAdvanced
    disableDebugBuild = this.&disableDeugBuild

}

2.settings.gradle中,调用include把需要包含的子project加进来,示例如下:

include ':app', ':JavaLibrary'

/**
  * 这个函数的目的是:
  * 1.解析local.properties的文件,读取Android SDK 和NDK的路径
  * 2.获取最终产出目录的路径,这样,编译完的apk或者jar包将拷贝到这个最终产出物目录中
  * 3.获取Android SDK指定编译的版本
 **/

def initEnvironment(){
    println "initialize gradle environment start"
    Properties properties = new Properties()
    File properFile = new File(rootDir.getAbsolutePath()+"/local.properties")
    properties.load(properFile.newDataInputStream())

    /**
     *  settings对象创建位于具体的project创建之前,而gradle对象已经创建好了,所以将local.properties信息读出来后,
     *  通过extra属性方式设置到gradle对象中,而具体的project执行时,就可以直接从gradle对象中得到这些属性了
     */
    gradle.ext.api = properties.getProperty('sdk.api')
    gradle.ext.sdkDir = properties.getProperty('sdk.dir')
    gradle.ext.ndkDir = properties.getProperty('ndk.dir')
    gradle.ext.localDir = properties.getProperty('local.dir')
    //指定debug keystore文件位置,debug版apk签名时会用到
    gradle.ext.debugKeyStore = properties.getProperty('debug.keystore')
    
    println "initialize gradle environment complete"
    
}
//初始化
initEnvironment()

3.在local.properties中加入以上定义的参数

ndk.dir=/Users/jkk/Library/Android/sdk/ndk-bundle
sdk.dir=/Users/jkk/Library/Android/sdk
local.dir = /Users/jkk/E/dd-dir
debug.keystore = /Users/jkk/E/mykeystore.jks
sdk.api=android-28

4.再看看根目录下的build.gradle,主要是做一些全局配置


buildscript {
    ext.kotlin_version = '1.2.71'
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.2.1'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

这里其实可以用到好几种闭包,例如allproject{} , buildscript{},configurations{},reposities{},sourceSets{},subprojects{}等等,每个都有不同的含义,例如以下几种:
subprojects:遍历所有的子project,由于其他的闭包都在subprojects,所以其实相当于对每个project都配置了一些信息
buildscript:主要用来执行所依赖的classpath等信息
reposities:定义所以来的仓库

猜你喜欢

转载自blog.csdn.net/qq_26984087/article/details/87967770