Groovy是一种基于JVM(Java虚拟机)的敏捷开发语言,它结合了Python、Ruby和Smalltalk的许多强大的特性,Groovy代码能够与Java代码很好地结合
,也能用于扩展现有代码。由于其运行在 JVM 上的特性,Groovy也可以使用其它非Java语言编写的库
。
支持DSL语法特性
XML和HTML原生支持
对正则表达式的本地支持
return语句可选(默认返回最后一个语句)
方法,属性默认都是public的
Groovy不强迫捕获异常,看使用者需求
?.安全导航操作符的使用(kotlin借鉴了这个)
闭包的使用结合DSL语法特性等等
// 1、以java的方式写groovy
class HelloGroovy{
static void main(String[] args) {
for(int i = 0; i< 3 ;i ++){
println(test())
}
}
// 会自动返回最后一个语句,类型会自动判别
def test(){
// return "hello world"
"hello world"
}
}
// 2、以脚本(kotlin)的方式写groovy
3.times {
println("hello world")
}
class Two {
// 自动变量
def mile
// 只读变量
final year = 2027
// def 可以省略
private month = 12
}
def two = new Two(mile: 1000)
// 因为 year只读,下面这种方式报错
// def twotwo = new Two(mile: 1000, year: 1111)
// 获取自动装箱的类型
println two.mile.class
println two.mile.getClass()
结果
class java.lang.Integer
class java.lang.Integer
但如果有插值表达式使用的话,就是groovy.lang.GString类型
def name = "carName"
def realName = "$name:AAAA"
println realName
println name.getClass()
println realName.getClass()
结果
carName:AAAA
class java.lang.String
class org.codehaus.groovy.runtime.GStringImpl
// 关于自动装箱
def method(Object obj){
1
}
def method(String str){
2
}
Object o = new Object()
println "method${method(o)} is invoked"
Object obj = "A" // 推断是String类型
println "method${method(obj)} is invoked"
结果
method1 is invoked
method2 is invoked
// 看起来是数组,实际是ArrayList类型
def array = [1, 2, 3]
println array.getClass()
// 下面这个才是数组类型
int[] array2 = [1, 2, 3]
println array2.getClass()
// 数组的另一个写法
def array3 = [1, 2, 3] as int[]
println array3.getClass()
结果
class java.util.ArrayList
class [I
class [I
数组的自动装箱
String[] strArray = ["1", 2, "3"]
println strArray.getClass()
println strArray[1].getClass()
结果
class [Ljava.lang.String;
class java.lang.String
范围是一种特殊的列表,由序列中的第一个和最后一个值表示,Range可以是包含或排除。包含范围包括从第一个到最后一个的所有值,而独占范围包括除最后一个之外的所有值。也可以使用表达式来表示范围
(1..3).forEach{
println "hello world : " + it
if(it == 2){
println("2222")
}
}
结果
hello world : 1
hello world : 2
2222
hello world : 3
class groovy.lang.IntRange
在Groovy中可以使用特定的表述方式来指定映射
def map = [a: 11, b: 12]
map.forEach{k,v ->
println "keyType=${k.class} key=$k, value=$v"
}
println "map['a'] = " + map['a']
结果
keyType=class java.lang.String key=a, value=11
keyType=class java.lang.String key=b, value=12
map['a'] = 11
Integer.metaClass.add1000{
delegate+1000
}
println 250.add1000()
结果
1250
闭包,gradle中有很多这种写法
class Car{
def miles
private year = 2027
def closureTest(def param1, Closure closure){
}
}
new Car().closureTest(1){
}
groovy默认会为类中的变量生产getter/setter方法
car.miles = 2000
println car.miles
对变量的赋值和获取,默认是调用的getter/setter方法
Groovy对于private修饰的变量没有强制性
可以重写getter/setter方法(也可以看到privacy
修饰符不起作用)
class Car{
def miles
private year = 2027
def getMiles() {
println "in getMiles"
return miles
}
void setMiles(miles) {
println "in setMiles"
this.miles = miles
}
def getYear() {
println "in getYear"
return year
}
void setYear(year) {
println "in setYear"
this.year = year
}
}
def car = new Car()
car.miles = 2000
println car.miles
car.year = 2028
println car.year
结果
in setMiles
in getMiles
2000
in setYear
in getYear
2028
如何让privacy
修饰符起作用,通过抛出异常(groovy的语言不是为了安全,是为了便捷,解决这种没多大意义
)
class Car{
def miles
private year = 2027
def getMiles() {
println "in getMiles"
return miles
}
void setMiles(miles) {
println "in setMiles"
this.miles = miles
}
def getYear() {
throw new IllegalAccessException("can not get")
println "in getYear"
return year
}
void setYear(year) {
throw new IllegalAccessException("can not set")
println "in setYear"
this.year = year
}
}
def car = new Car()
car.miles = 2000
println car.miles
car.year = 2028
println car.year
不通过getter/setter,直接操作变量
car.@mails = 2000
多种访问get/set方式
Car car = new Car()
car.'miles' = 10000
car['miles'] = 30000
println car.'miles'
def str = 'miles'
car."$str" = 20000
构造方法
正常创建一个对象
class Car{
def miles
private year = 2027
def getMiles() {
println "in getMiles"
return miles
}
void setMiles(miles) {
println "in setMiles"
this.miles = miles
}
def getYear() {
println "in getYear"
return year
}
void setYear(year) {
println "in setYear"
this.year = year
}
}
def car = new Car(miles: 1000, year: 2028)
结果
in setMiles
in setYear
添加一个构造函数,只接收miles
class Car{
def miles
private year = 2027
def getMiles() {
println "in getMiles"
return miles
}
void setMiles(miles) {
println "in setMiles"
this.miles = miles
}
def getYear() {
println "in getYear"
return year
}
void setYear(year) {
println "in setYear"
this.year = year
}
Car(miles){
this.miles = miles
}
}
def car = new Car(miles: 1000, year: 2028)
println car.miles
println car.miles.getClass()
结果
in getMiles
[miles:1000, year:2028]
in getMiles
class java.util.LinkedHashMap
1、可以看到,创建对象时,new Car中传递参数是当做map进行传递的
2、由于 下面构造方式没有指明参数类型,就把miles当做Object对象,接受了传递进来的map对象
Car(miles){
this.miles = miles
}
如果想让只具名参数和只接收一个参数的构造方法生效
class Car{
def miles
private year = 2027
def getMiles() {
println "in getMiles"
return miles
}
void setMiles(miles) {
println "in setMiles"
this.miles = miles
}
def getYear() {
println "in getYear"
return year
}
void setYear(year) {
println "in setYear"
this.year = year
}
Car(){
}
Car(int miles){
this.miles = miles
}
}
def car = new Car(miles: 1000, year: 2028)
println car.miles
println car.miles.getClass()
def car2 = new Car(miles: 2000)
println car2.miles
println car2.miles.getClass()
结果
in setMiles
in setYear
in getMiles
1000
in getMiles
class java.lang.Integer
in setMiles
in getMiles
2000
in getMiles
class java.lang.Integer
普通类中方法不支持具名参数 - 神经病
class Car {
def miles
def year
void execute(x = 1, y = 2, z=3) {
println "$x $y $z"
}
}
Car c = new Car()
c.execute(x: 1, y: 2, z: 3) // 不支持具名参数,会把传递进来的方法当做map
c.execute(x: 1, y: 2, z: 3, 2222, 3333) // 这个是可以的,正常的(传递了3个参数,一个是map,和两个整数)
c.execute(x: 1, y: 2, z: 3, 2222, c: 111, 3333, a: 111, b: 222) // 这个也是可以的,多有的键值对合并,成为第一个参数
// 下面的结果,xyz结果都是1,2,3 没有用到变量进行赋值
c.execute(x = 1, y = 2, z = 3)
c.execute(x = 1, z = 2, y = 3)
默认参数
class Car {
def miles
def year
void execute(x = 1, y = 2, z=3) {
println "$x $y $z"
}
// 这个会报错,这和kotlin一样
void execute() {
println "$x $y $z"
}
}
Groovy中可以理解为闭包就是可执行的代码块,或匿名函数。闭包在使用上与函数与许多共通之处,但是闭包可以作为一个函数的参数
一个最简单的闭包
def closure = {
// 这个里面和方法体一样
// 默认接收一个参数,参数直接使用it
}
// 有一个默认参数的闭包
def closure = {
println it
}
closure("show this")
// 没有默认参数的闭包
def closure = {
->
println "not arguments"
}
closure()
// 定义多参数的闭包,支持默认值
def closure = {
arg1="ccc", arg2 ->
println "$arg1 and $arg2"
}
closure("aaa", "bbb")
闭包就是Closure对象
def abc = {
}
println abc.class
结果 - 动态运行时生成的
class com.study.class1.TwoThis$_run_closure2
闭包可以作为方法的参数
def func(closure) {
closure()
}
func {
// 闭包执行的代码
println "call"
}
柯里化闭包
闭包与接口/类进行转换
interface Action {
void aaa()
}
def closure = {
println "aaa"
}
Action action = closure
action.aaa()
println closure.class
println action.class // 动态代理对象
interface Action {
void aaa()
void bbb()
void ccc()
}
def addTextWatcher(Action action) {
action.aaa()
}
addTextWatcher({
println "aaa"
} as Action)
// 当有接口有多个方法时,传入的闭包要强转为Action,使用as关键字
// 现在看起来就像是gradle中的内容了
闭包中的内容是通过Closure中的call方法进行调用
interface Action {
void call()
}
def func(closure) {
closure()
}
Action closure = new Action() {
@Override
void call() {
println "call"
}
} as Closure
func(closure)
类当中如果定义了call方法,可以直接使用对象()去调用call方法
class Action {
void call(a) {
println "$a"
}
}
def a = new Action()
a(111)
Closure比较重要的成员变量
private Object delegate;
private Object owner;
private Object thisObject;
// delegate、owner、thisObject
// 在普通闭包中,都是定义这个普通闭包的对象
// 在静态闭包中,都是定义这个静态闭包的类
private int resolveStrategy = OWNER_FIRST;
protected Class[] parameterTypes; // 参数类型
protected int maximumNumberOfParameters; // 参数个数
def closure = {
int a, int b ->
println a.getClass()
println b.getClass()
}
closure(1, 2)
println closure.parameterTypes
println closure.maximumNumberOfParameters
def closure2 = {
println "this is" + this
println "owner is" + owner
println "delegate is" + delegate
}
closure2()
class Test {
def closure2 = {
println "this is" + this
println "owner is" + owner
println "delegate is" + delegate
}
}
class Test {
static def closure2 = {
println "this is" + this
println "owner is" + owner
println "delegate is" + delegate
}
}
class Test {
def closure1 = {
def closure2 = {
// this:Test@2b76ff4e,定义它的时候的类的this,当它是static时就是class对象
println "this is" + this
// owner:Test$_closure1@8c3619e,定义它的时候的类的对象
println "owner is" + owner
// delegate:Test$_closure1@8c3619e,默认就是owner, 但是代理可以修改
println "delegate is" + delegate
}
closure2()
}
}
闭包中代理策略
在脚本中,func不在类中,下面的脚本可以直接访问
def func(){
println "func"
}
def closure = {
func()
}
closure()
当func在类中时,下面闭包访问就报错
class Test2 {
def func() {
println "Test2 func"
}
}
def closure = {
func()
}
closure()
修改代理,就能访问了
class Test2 {
def func() {
println "Test2 func"
}
}
def closure = {
func()
}
closure.delegate = new Test2()
closure()
但是下面的代码结果是Script func
class Test2 {
def func() {
println "Test2 func"
}
}
def func() {
println "Script func"
}
def closure = {
func()
}
closure.delegate = new Test2()
closure()
修改代理,修改策略
class Test2 {
def func() {
println "Test2 func"
}
}
def func() {
println "Script func"
}
def closure = {
func()
}
closure()
closure.delegate = new Test2()// 优先选择的是owner
//* @see groovy.lang.Closure#DELEGATE_FIRST
//* @see groovy.lang.Closure#DELEGATE_ONLY
//* @see groovy.lang.Closure#OWNER_FIRST
//* @see groovy.lang.Closure#OWNER_ONLY
//* @see groovy.lang.Closure#TO_SELF
closure.resolveStrategy=Closure.DELEGATE_ONLY
closure()
groovy的动态特性
class User {
def username = 'zee'
String age
void setName(String name) {
println "setName(String name)"
this.username = name
}
void setName(Object name) {
println "setName(Object name)"
this.username = name
}
}
def user = new User()
println user.username.class
user.username = new Object()
println user.username.class
user.username = 123
println user.username.class
user.username = new User()
println user.username.class
def user1 = new User()
Object name = "zee"
println name.class
user1.setName(name)
name = 123
println name.class
user1.setName(name)
def user3 = new User()
user3.age = "123"
user3.age = 123 // groovy是强类型的,动态的,这里int可以转成 String
println user3.age
结果
class java.lang.String
class java.lang.Object
class java.lang.Integer
class com.study.class1.User
class java.lang.String
setName(String name)
class java.lang.Integer
setName(Object name)
123
groovy不会进行安全检查,在运行时候才抛出异常
class Person1 {
def dream() {
println "I have a dream!"
}
}
class Person2 {
def dream() {
println "I have a dream!"
}
}
def func(person){
person.dream()
}
def person1 = new Person1()
def person2 = new Person2()
func(person1)
func(person2)
使用@TypeChecked强制编译检查,但是会损失动态特性
class Person1 {
def dream() {
println "I have a dream!"
}
}
class Person2 {
def dream() {
println "I have a dream!"
}
}
@TypeChecked
def func(Person1 person) { // 这里必须指定类型
person.dream()
}
def person1 = new Person1()
def person2 = new Person2()
func(person1)
func(person2)
@TypeChecked
class Test {
@TypeChecked(TypeCheckingMode.SKIP) // 跳过检查
def func(person) {
person.dream()
}
}
动态特性
元编程
MOP方法拦截
class Person implements GroovyInterceptable {
def func() {
System.out.println "I have a dream!"
}
@Override
Object invokeMethod(String name, Object args) {
//println "invokeMethod"
System.out.println "$name invokeMethod"
//respondsTo(name) //判断方法是否存在
if (metaClass.invokeMethod(this, 'respondsTo', name, args)) {
System.out.println "$name 方法存在"
System.out.println "$name 执行前.."
metaClass.invokeMethod(this, name, args)
System.out.println "$name 执行后.."
}
}
}
new Person().func()
结果
func invokeMethod
func 方法存在
func 执行前..
I have a dream!
func 执行后..
这里拦截某个对象的某一个方法
class Person3 {
def func() {
System.out.println "I have a dream!"
}
}
def person3 = new Person3()
// 这里拦截某个对象的某一个方法
person3.metaClass.func = {
println "I have a new dream !!!"
}
person3.func()
// 拦截所有的方法
person3.metaClass.invokeMethod = {
String name, Object args ->// invokeMethod(String name, Object args)
println "$name 被拦截"
}
person3.func()
拦截所有实例的方法
Person3.metaClass.invokeMethod = {
String name, Object args ->// invokeMethod(String name, Object args)
println "$name 被拦截"
}
对内置String进行拦截
String.metaClass.invokeMethod = {
String name, Object args ->
println "String.metaClass.invokeMethod"
MetaMethod method = delegate.metaClass.getMetaMethod(name)
if (method != null && name == 'toString') {
"showme"
}
}
println "jason".toString()
MOP方法注入
方法注入:编写代码时知道想要添加到一个或多个类中的方法的名字。利用方法注入,可以动态地向类中添加行为。也可以向任意数目的类中注入一组实现某一特定功能的可服用方法,就像工具函数。有以下几种方式
使用MetaClass来注入方法
class Person4 {
def func() {
System.out.println "I have a dream!"
}
}
println Person4.metaClass // 注入前:org.codehaus.groovy.runtime.HandleMetaClass
Person4.metaClass.newFunc = {
println "newFunc调用"
}
println Person4.metaClass // 注入后:groovy.lang.ExpandoMetaClass
使用groovy.lang.ExpandoMetaClass来注入方法
def emc = new ExpandoMetaClass(Person4)
emc.func2 = {
println "func2"
}
emc.initialize()
Person4.metaClass = emc
new Person4().func2()
使用分类注入方法 - 场景,框架工具类
class StringUtils {
// public static String isEmpty(){
//
// }
static def isNotEmpty(String self) {
println "isNotEmpty"
self != null && self.length() > 0
}
}
class StringUtils2 {
static def isNotEmpty(Integer self) {
println "isNotEmpty2"
//self != null && self.length() > 0
}
}
use(StringUtils, StringUtils2) { // 从后往前找
println "".isNotEmpty()
println 1.isNotEmpty()
}
其他写法
@Category(String)
class StringUtils2 {
def isNotEmpty() {
println "isNotEmpty2"
this != null && this.length() > 0
}
}
use(StringUtils2) {
println "".isNotEmpty()
}
操作不存在的变量、方法
class Person5 {
def username
// 对不存在的变量进行get操作
def propertyMissing(String name) {
println "propertyMissing"
if (name == 'age') {
"19" // 返回默认值
}
}
// 对不存在的变量进行set操作
def propertyMissing(String name, def arg) {
println "propertyMissing ${name} : arg${arg}"
return "default"// 给与返回值
}
def methodMissing(String name, def arg) {
println "$name methodMissing"
if (name.startsWith 'getFather') {
"zzzz"
}
}
}
def p = new Person5()
println p.age = 12
println p.age
println p.getFather()
运算符重载方法列表
a + b a.plus(b)
a – b a.minus(b)
a * b a.multiply(b)
a ** b a.power(b)
a / b a.div(b)
a % b a.mod(b)
a | b a.or(b)
a & b a.and(b)
a ^ b a.xor(b)
a++ or ++a a.next()
a– or –a a.previous()
a[b] a.getAt(b)
a[b] = c a.putAt(b, c)
a << b a.leftShift(b)
a >> b a.rightShift(b)
~a a.bitwiseNegate()
-a a.negative()
+a a.positive()
switch(a) { case(b) : }
b.isCase(a)
a == b
a.equals(b) or a.compareTo(b) == 0
a != b
! a.equals(b)
a <=> b
a.compareTo(b)
a > b
a.compareTo(b) > 0
a >= b
a.compareTo(b) >= 0
a < b
a.compareTo(b) < 0
a <= b
a.compareTo(b) <= 0
class TestA {
def plus(TestA newTestA) {
// 处理业务
}
}
new TestA() + new TestA()
Integer.metaClass.plus = {
int a ->
"$delegate + $a"
}
println 1 + 2
def e = new Expando(name: "Aaa", func: {
println "func"
})
e.a = 123
println e.a
https://blog.csdn.net/nihaomabmt/article/details/112308851
gradle使用安卓插件编译android项目
获取gradle
这里使用本地缓存的gradle工具包
C:\Users\showme.gradle\wrapper\dists\gradle-7.4.2-bin\48ivgl02cpt2ed3fh9dbalvx8\gradle-7.4.2
系统属性配置
添加 GRADLE_HOME C:\Users\showme.gradle\wrapper\dists\gradle-7.4.2-bin\48ivgl02cpt2ed3fh9dbalvx8\gradle-7.4.2
添加 Path %GRADLE_HOME%\bin
通过命令行终端输入gradle --version 查看是否配置成功
PS C:\Users\showme> gradle --version
------------------------------------------------------------
Gradle 7.4.2
------------------------------------------------------------
Build time: 2022-03-31 15:25:29 UTC
Revision: 540473b8118064efcc264694cbcaa4b677f61041
Kotlin: 1.5.31
Groovy: 3.0.9
Ant: Apache Ant(TM) version 1.10.11 compiled on July 10 2021
JVM: 17.0.2 (Oracle Corporation 17.0.2+8-LTS-86)
OS: Windows 10 10.0 amd64
在工程文件夹下,创建一个build.gradle文件,包含内容
println 'Hello, Gradle!'
build.gradle是构建Project的核心文件,也是入口
打开cmd终端,移动到工程目录下,执行命令:> gradle help
$ gradle help [0:31:04]
Starting a Gradle Daemon (subsequent builds will be faster)
> Configure project :
Hello, Gradle!
> Task :help
Welcome to Gradle 7.4.2.
To run a build, run gradle <task> ...
To see a list of available tasks, run gradle tasks
To see more detail about a task, run gradle help --task <task>
To see a list of command-line options, run gradle --help
For more detail on using Gradle, see https://docs.gradle.org/7.4.2/userguide/command_line_interface.html
For troubleshooting, visit https://help.gradle.org
从输出可以看到
Gradle Daemon
在看一下,目录下当前没有生产额外的文件
showme@showmedeMBP: ~/workspace/tmmmp/hello_gradle
$ tree . [0:34:09]
.
└── build.gradle
0 directories, 1 file
gradle wrapper
gradlew和gradlew.bat分别是Linux和Windows下的可执行脚本
showme@showmedeMBP: ~/workspace/tmmmp/hello_gradle
$ gradle wrapper [0:37:24]
> Configure project :
Hello, Gradle!
BUILD SUCCESSFUL in 696ms
1 actionable task: 1 executed
showme@showmedeMBP: ~/workspace/tmmmp/hello_gradle
$ tree . [0:37:31]
.
├── build.gradle
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
└── gradlew.bat
2 directories, 5 files
gradle/wrapper/gradle-wrapper.properties文件的目的:在不同的机器上快速部署gradle执行环境
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionBase 下载的Gradle压缩包解压后存储的主目录
zipStorePath | distributionPath: 本地缓存的gradle可执行文件路径, 默认在 ~/.gradle/wrapper/dists
distributionUrl 下载特定gradle版本
https://services.gradle.org/distributions/gradle-7.4.2-bin.zip
https://services.gradle.org/distributions/gradle-7.4.2-all.zip
bin和all的区别,bin只包含了可执行文件相关的内容,all还包含了gradle的源码和帮助文档
GRADLE_USER_HOME
gradlew命令行
gradle标准工程
showme@showmedeMBP: ~/workspace/tmmmp/hello_gradle
$ tree . [0:37:31]
.
├── build.gradle
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
└── gradlew.bat
java中的标准工程
安卓中的标准工程:有一个app模块,在这个模块中包含也包含了一个build.gradle
Gradle DSL
App->build.gradle文件 , 使用的就是groovy 语言
plugins {
id 'com.android.application'
}
android {
compileSdk 32
defaultConfig {
applicationId "com.example.studygradle"
minSdk 26
targetSdk 32
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
在android studio中新增java模块(多层次的模块写法 - 这个冒号就相当于文件夹的斜杆
)
可以看到setting.gradle通过include命令引入的模块,已经分层方式
模块不include进来,则该模块不会进行构建
可以点进去看include细节,发现是gradle构建工具的一个方法
rootProject.name 配置的是整个工程最顶层的名字
配置阶段
解析每个Project中的build.gradle,解析过程中并不会执行各个build.gradle中的task
Configuration会建立一个有向图来描述Task之间的依赖关系,所有Project配置完成后,会有一个回调project.afterEvaluate(),表示所有的模块都已经配置完了
支持驼峰简写
自定义的任务默认分组到other中
自定义task类
// 通过自定义任务类来实现自定义任务
class MyTask extends DefaultTask {
@Input
String filePath // 可以指定filePath来传入n个文件的路径
@OutputFile
File file
MyTask() {
group "自定义任务"
description "自定义任务描述"
}
@TaskAction
void action() {
println "MyTask action()"
}
@TaskAction
void action2() {
println "MyTask action2()"
}
}
// 继承自定义的task类,并创建新的task
task myTask2(type: MyTask) {
filePath = 'xxx/xxx'
file = file('test.txt')
}
// 继承已有的task
task clean(type: Delete) {
delete rootProject.buildDir
}
task之间的集成和依赖关系
// Gradle3.0 << ,在4.x以上就废弃了
task A {
println "configuration A.."
doFirst {
println "doFirst A.."
}
doLast {
println "doLast A1.."
}
doLast {
println "doLast A2.."
}
doLast {
println "doLast A3.."
}
}
A.doLast {
println "doLast A4.."
}
task C {
println "configuration C.."
doLast {
println "doLast C.."
}
}
task B {
println "configuration B.."
doLast {
println "doLast B.."
}
}
task hello2(dependsOn: [A, C, B]) {
doLast {
println "doLast hello2"
}
}
A.dependsOn B
A.mustRunAfter(B)
A.shouldRunAfter B
task finalized {
doLast {
println "清理任务"
}
}
A.finalizedBy finalized
依赖其他build.gradle文件
1)创建一个gradle文件
config.gradle
task CCCC {
doLast {
println "doLast.."
}
}
2)依赖创建的其他gradle文件
apply from: 'config.gradle'
class ZipTask extends DefaultTask {
// @Input
// @Optional
// 表示可选
String from
// @OutputFile
// @Optional
// 表示可选
File out
ZipTask() {
outputs.upToDateWhen {
false// 增量构建,每次都会开启,不会跳过任务
}
}
@TaskAction
void fun() {
println " @TaskAction fun()"
println from
println out
//文件进行操作
//inputs.files.first()
println inputs.files.singleFile
def inFile = inputs.files.singleFile
def file = outputs.files.singleFile
file.createNewFile()
file.text = inFile.text
}
}
task myTask(type: ZipTask) {
from = "a/b/c" // 输入
out = file("test.txt") // 输出
inputs.file file('build.gradle')
outputs.file file('test.txt')
}
使用自定义任务,实现zip打包packageDebug输出的内容
task zip(type: Zip) {
archiveName "outputs.zip"// 输出的文件名字
destinationDir file("${buildDir}/custom")// 输出的文件存放的文件夹
from "${buildDir}/outputs"// 输入的文件
}
压缩packageDebug任务的输出文件
afterEvaluate {
println tasks.getByName("packageDebug")
task zip(type: Zip) {
archiveName "outputs2.zip"// 输出的文件名字
destinationDir file("${buildDir}/custom")// 输出的文件存放的文件夹
from tasks.getByName("packageDebug").outputs.files// 输入的文件
tasks.getByName("packageDebug").outputs.files.each {
println it
}
}
}
在根build.gradle文件中,给app模块进行配置
project(':app') {
// plugins {
// id 'com.android.application'
// id 'kotlin-android'
// }
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
android {
compileSdkVersion 30
buildToolsVersion "30.0.2"
defaultConfig {
applicationId "com.dongnaoedu.gradledemo"
minSdkVersion 28
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.2.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'com.google.android.material:material:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
}