【二】Gradle 基础知识学习笔记

最近在学习Gradle,感觉真的很实用的,这里写一下学习笔记吧,以后还可以再来看看。

一、Groovy 语法

先了解一下Groovy语法,新建一个build.gradle文件,然后加上这样一行:task groovy << {},然后再添加下面的各种类型操作,执行方式:gradle groovy 即可

1. 定义变量及函数:

a. 型1

def name = "yk3372"

def myFunc = {
    println "hello world $name"
}
myFunc()

输出:hello world yk3372

b. 型2
groovy的方法可以当成变量来传递(函数指针?),类似这样:

def myFunc2 = myFunc
myFunc2() // 还可以继续当成函数调用

c. 型3

def doubleIt = {x -> x + x} //闭包
def applyFuncTwice(func, arg) { //高阶函数
    func(func(arg))
}
def foo = 5
def fooDoubleTwice = applyFuncTwice(doubleIt, foo)
println "执行两次函数结果:$fooDoubleTwice"

输出:执行两次函数结果:20

2. 列表及遍历

def mylist = ["first", "second", "third"] //列表
def printItem = { item -> println "item: $item" } //闭包函数
mylist.each(printItem)  // 遍历,传入上面的方法,执行相应操作
// 还可以简化输出:
mylist.each{println "item: $it"}//结果一样 it可以看成默认遍历的每一项,类似上面item参数

输出:

item: first
item: second
item: third

3. 类定义(跟java类似)

class MyClass {
    String name = "yk3372"
    def echoMyName() {
        println "my id is: $name"
    }
}
def classer = new MyClass()
classer.echoMyName()
classer.name = "Jack"//看起来可以直接修改,没有private之类的东西
classer.echoMyName()

输出:

my id is: yk3372
my id is: Jack

4. 闭包设置代理对象

class MyClass {
    String name = "yk3372"
    def echoMyName() {
        println "my id is: $name"
    }
}
def classer = new MyClass()

def nameClosure = {
    name = "Jack" //没有声明类型
    echoMyName() //直接调用函数
}

nameClosure.delegate = classer
nameClosure()

输出:my id is: Jack

发现成功修改了代理类对象的成员变量和调用里面的函数,第一次见 这种语法~~
ps:我觉得可以理解成这样(不确保正确):

def nameClosure(MyClass myclass){
    myclass.name = "Jack"
    myclass.echoMyName()
}
//猜想,应该是设置完闭包的代理后,相当于里面默认的this变成MyClass的对象了,然后就可以随意更改和调用了~ 让我想到了C++的友元函数?好久没写了不确定,有兴趣可以去查查^_^

二、 Gradle Tasks

task 从名字上看任务,它可以帮我们做一些预定好的操作,比如针对编译android,我们要先编译java文件->class文件,然后打包dex文件,处理res文件….最后生成apk文件。
如果我们手动去做这件事件,会非常累,都是些体力活,重复劳动,因此我们就需要各种各样的task帮我们做这些事情,写一次,以后每次运行一下任务即可。
流程图
这样我们就可以方便的得到想要的结果了。

1. 定义Task

a.我们先看这几种:

project.task("task1")
task("task2")
task "task3"
task myTask4

然后我们运行一下gradle tasks
在Other tasks下面输出了(字母表排序):

myTask4
task1
task2
task3

b. 对上面第4种方式进行详细化

task myTask4
myTask4.description = "task 4 desp" // 描述
myTask4.group = "task4 group" // 分组名,默认在other task分组里
myTask4.doLast{println "do the last"} // 执行task时做的事情,每个task最后默认要执行的函数闭包

输出:

Task4 group tasks
-----------------
myTask4 - task 4 desp

Other tasks
-----------
task1
task2
task3

————————————————————————————————
然后我们再执行一下task4,输入
gradle myTask4
输出:

:myTask4
do the last

————————————————————————————————

task myTask4
myTask4.doLast{println "do the last"} //最后执行
myTask4.doFirst{println "do the first"} // 开始执行
myTask4.leftShift{println "left shift > after doLast"} // 最后的后面执行,类似doLast
myTask4 << { // 简单的task
    println "hello"
}
task myTask5 << {// 简单的task声明,并传递一个闭包
    println "task5"
}

输出:

:myTask4
do the first
do the last
left shift > after doLast
hello

c. task的另一种定义(类似类定义)

task myTask6 {
    description "desp"// 等价于: description("desp") 其实是函数调用,不需要等号
    group "my group"
    doLast {
        println "hello"
    }
}

结果就不写了,跟上面类似

2. Task之间依赖关系

a. dependsOn:(在android gradle可能是以参数名方式传入,后面会介绍)
比如有两个task,task1 task2,task2的执行要依赖task1的结果,那我们可以这样写:

task task1 {
    doLast{
        println "task1"
    }
}

task task2 {
    dependsOn task1
    doLast{
        println "task2"
    }
}

我们执行一下task2:gradle -q task2 -q 是忽略其他信息
输出:

task1
task2

很好,跟我们想的一样

b. finalizedBy:(理解为由xxx来结束的)
比如这种场景:cleanBuild,我们一般先clean,再build,用上面场景也可以,这里我们可以以clean为基准,来实现:

task buildApk {
    doLast{
        println "build"
    }
}

task cleanAndBuild {
    finalizedBy buildApk
    doLast{
        println "clean"
    }
}

结果如我们所想先输出clean,后输出build
注:我在写这个的时候发现如果task:buildapk如果放在clean的后面,执行会出错,说找不到property buildApk,解决办法就是这样写:
finalizedBy "buildApk"
然后就可以正确运行了~~感觉像个声明?
c. shouldRunAfter
我的理解是,有任务A、B,两个任务需要都运行,但B的运行需要A运行后执行,然后run A,B,最后执行顺序是:A,B,我们拿AS点击运行,然后就会编译安装APK来模拟下,看看代码来理解:

task RunApk {
    doLast{
        println "RunApk"
    }
}

task installApk {
    shouldRunAfter RunApk
    doLast{
        println "installApk"
    }
}

我们执行这个:gradle -q installApk RunApk 不需要区分任务前后
得到结果:

RunApk
installApk

当然,一个事情的做法可以有多种多样,这里只是举个例子来使用这个而已,不一定典型


讲完上面三个后我们再来综合用一下:
现在有buildApk installApk runApk 3个子任务,然后我想写一个总任务叫:installAndRunApk,依赖上面3个子任务写法如下:

task buildApk << {
    println "buildApk"
}
task installApk << {
    println "installApk"
}
task runApk << {
    println "runApk"
}

task installAndRunApk {
    dependsOn = ["installApk", "runApk", "buildApk"]
}

输出结果:

buildApk
installApk
runApk

看起来是不是好神奇,顺序竟然对了,我纳闷了好久,发现原来列表是按照字母表排序 >_< 的,好吧,我们来改一下:

task c_buildApk << {
    println "c_buildApk"
}
task b_installApk << {
    println "b_installApk"
}
task a_runApk << {
    println "a_runApk"
}

task installAndRunApk {
    dependsOn = ["b_installApk", "a_runApk", "c_buildApk"]
}

哼哼,这次结果就不对了:

a_runApk
b_installApk
c_buildApk

接下来我们来设置一下约束:

task installAndRunApk {
    dependsOn = ["b_installApk", "a_runApk", "c_buildApk"]
    b_installApk.mustRunAfter c_buildApk
    a_runApk.mustRunAfter b_installApk
}

然后再来执行一下gradle -q installAndRunApk
输出:

c_buildApk
b_installApk
a_runApk

dependsOn 除了使用列表外,我们还可以做循环找到匹配的task,写法如下:

task filterApkTask {
    dependsOn tasks.matching{ task -> task.name.endWith("Apk")}
    doLast {
        println "filter task end with Apk"
    }
}

3. Task 具体使用(Task types)

上面说了很多task的定义,依赖之类的逻辑处理,那我们该如何应用到项目呢?下面就来说几种使用方式,其他的可以来这里查文档,这里就入门而已
a. Copy
先来看一下下面的task

task copyImages(type: Copy) {
    from 'images'
    include '*.jpg'
    into 'build'
}
// 这个task翻译过来就是这样:把images文件夹里面的jpg文件,复制到build目录下

平时开发时也经常会有这种复制移动需求,这个就可以很好的帮我们做到,只要运行一下这个task就行。具体的Copy参数,我们可以点这里面看一下文档。
我们还可以做个组合任务:

task copyImagesFolders(type: Copy) {
    from('images') {
        include '*.jpg'
        into 'jpeg'
    }
    from('images') {
        include '*.gif'
        into 'gif'
    }
    into 'build'
}
//相当于分类图片,放到不同文件夹,然后把两个文件夹放到build里

除了复制还有删除移动之类的操作,具体可以查阅DSL文档
b. Zip 压缩

task zipImages(type: Zip) {
    baseName = 'images'
    destinationDir = file('build') //java 文件类型
    from 'images'
}

c. 生成Jar包
跟Copy类似,在Gradle里都叫Task Type,作为参数传进去实现对应的功能,类似还有我们可能会常用的Jar包,来看个例子,这个是将lib库生成的class文件,进行打包:

task buildLib(type: Jar) {
    from(project.buildDir.toString() + '/intermediates/classes/release')// filepath
    destinationDir file(project.buildDir.toString() + '/aa') // file
    baseName 'abc' // jar name
    manifest {// META-INF/MANIFEST.MF 文件
        attributes 'Main-Class': 'MainFrame' // 启动类
        attributes 'Class-Path': '.'
        attributes 'Manifest-Version': '1.0'
    }
}

然后我们运行,就可以在build目录下发现aa目录里有个叫abc.jar
原文地址:http://blog.csdn.net/yk3372/article/details/53045873

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值