Gardle——深入

Groovy语法

Groovy是运行于JVM上的动态语言(在运行时不用指定变量类型,动态改变数据类型 )

${}用于一般替代字串或者表达式

闭包

闭包是可以用作方法参数的代码块,象是方法指针,代码在某处被定义然后在其后的调用处执行。
定义闭包

{ [closureParameters -> ] statements }

调用

闭包对象.call(参数)

闭包对象(参数)

参数

{ int a, int b=2 -> a+b }

参数类型可选
参数可以设定默认值
用逗号分隔

隐含参数
当闭包没有显式定义参数列表时,有一个隐式的it参数

闭包的简写
闭包作为闭包或方法的最后一个参数,可以将闭包从参数圆括号中提取出来接在最后
如果闭包是唯一的一个参数,则闭包或方法参数所在的圆括号也可以省略
对于有多个闭包参数的,只要是在参数声明最后的,均可以按提取省略


Gradle文件操作

确定文件的位置

Project.file(java.lang.Object)方法

File configFile = file('src/config.xml')

文件集合

Project.files(java.lang.Object[])方法
可以把集合,迭代变量,map和数组传递给files()方法。它们会被展开,并且内容会转换为 File 实例

FileCollection collection = files('src/file1.txt',
                                  new File('src/file2.txt'),
                                  ['src/file3.txt', 'src/file4.txt'],
                                  Paths.get('src', 'file5.txt'))

文件树

按照层次结构划分的文件集合

def myTree = fileTree(dir:'src', excludes:['**/ignore/**', '**/.data/**'])

task copy(type: Copy) {
    from myTree
}

include 和 exclude 的含义:
org.gradle.api.tasks.util.PatternFilterable接口定义的方法

  • '*' 匹配任意数量的字符
  • '?' 匹配任意一个字符
  • '**' 匹配任意数量的目录或文件
task copyAllPdfReportsForArchiving(type: Copy) {
    from "${buildDir}/reports"
    include "**/*.pdf"
    into "${buildDir}/toArchive"
}

Gradle 依赖管理

依赖管理包括两部分,对获取依赖的管理以及生成发布的管理
涉及内容:管理依赖传递,解决版本冲突,使用

多数项目都不是完全独立的,而是需要依赖其他的项目
Gradle从远程仓库,本地目录,或者多项目构建中的另外一个项目获取依赖

依赖类型

常见依赖类型

  • 外部模块依赖
  • 项目依赖
  • 文件依赖
  • Client module dependency (外部模块中的一种,修改部分数据)

外部依赖

外部依赖通过group,name,version三个属性标识

dependencies {
    compile group: 'org.hibernate', name: 'hibernate-core', version: '3.6.7.Final'
}

快捷方式group:name:version

dependencies {
    compile 'org.hibernate:hibernate-core:3.6.7.Final'
}

项目依赖

dependencies {
   compile project(':shared')
}

文件依赖

dependencies {
    runtime files('libs/a.jar', 'libs/b.jar')
    runtime fileTree(dir: 'libs', include: '*.jar')
}

仓库Repositories

外部依赖是通过仓库来查找的

repositories {
    mavenCentral()
    jcenter()
    maven {
        url "http://repo.mycompany.com/maven2"
    }
}

同时还可以利用Gradle把jar包上传到远程仓库(publication artifacts)

排除依赖传递

gradle dependencies 查看依赖

|    |    \--- com.android.support:recyclerview-v7:25.3.1 -> 25.4.0
|    |         +--- com.android.support:support-annotations:25.4.0
|    |         +--- com.android.support:support-compat:25.4.0
|    |         |    \--- com.android.support:support-annotations:25.4.0
|    |         \--- com.android.support:support-core-ui:25.4.0
|    |              +--- com.android.support:support-annotations:25.4.0
|    |              \--- com.android.support:support-compat:25.4.0 (*)

25.3.1 -> 25.4.0是由于默认会优先版本高的依赖
(*)表示这个依赖被忽略了,这是因为已经有其他依赖传递了这个依赖

compile ('com.android.support:appcompat-v7:22.1.1@aar') {
    transitive = true//传递相关的依赖
}

排除模块

dependencies {
 compile('org.hibernate:hibernate:3.1') {
   //排除某个传递的依赖
   exclude module: 'cglib' /通过模块名称
   exclude group: 'org.jmock' //通过组名
   exclude group: 'org.unwanted', module: 'iAmBuggy' //通过组名和模块名称
 }
}   

Build生命周期

Gardle所有的构建任务,最终组成一个有向无循环图
在任何任务执行之前,都会先构造出一个完整的依赖图

构建阶段

一个Gradle构建有三个明显的阶段

  1. 初始化阶段(Initialization),通过setting.gradle决定哪些project参加构建,并创建相应的Project实例
  2. 配置阶段(Configuration),会去执行所有工程的build.gradle脚本
  3. 执行阶段(Execution),根据gradle命令传递过来的task名称,执行相应的任务集合

示例
settings.gradle 文件

println 'initialization phase 1'

build.gradle 文件

println 'configuration phase 2'

task configured {
    println 'configuration phase 3'
}

task test {
    doLast {
        println 'execution phase 5'
    }
}

task testBoth {
    doFirst {
      println `execution phase 6'
    }
    doLast {
      println 'execution phase 7'
    }
    println 'configuration phase 4'
}

执行命令

gradle test testBoth

执行的顺序就是println字符串最后的数字
可以看到默认的输出是在配制阶段执行的,

对生命周期做出响应

可以实现相应的监听接口或者可以提供一个在收到通知时要执行的闭包
例如 ProjectEvaluationListener 等接口

向具有某个属性的项目添加任务

allprojects {
    afterEvaluate { project ->
        if (project.hasTests) {
            println "Adding test task to $project"
            project.task('test') {
                doLast {
                    println "Running tests for $project"
                }
            }
        }
    }
}

Project.afterEvaluate()方法是在project评估(evaluated)后执行的


插件plugin

Gradle的核心是一个框架,所有很有用的特性,例如编译Java代码的能力,都是通过plugin添加的

作用

  • 提高复用,减少类似逻辑的配置过程
  • 进行更高层次的模块化,加强可读性和组织能力
  • 封装必要的逻辑

主要有两类插件,一种是脚本(script),一种是二进制(binary)插件
脚本插件添加进入构建脚本,用来更进一步配置构建,一般通过陈述的方式来控制构建
二进制脚本是实现Plugin接口的类,采用编程的方式来控制构建

使用插件

  1. Resolve插件,查找到对应版本的插件,添加到脚本的classpath中
  2. Apply插件,即执行插件Plugin.apply(T)

Script插件

apply from: 'other.gradle'

这一类的插件都是自行解析的,来自本地的文件系统,或者远程

二进制插件

通过提供 plugin id(一个全局唯一的标识符)应用插件
有核心插件(JavaPlugin) 和社区插件之分,核心插件可以使用简称(例如java
通过 plugins DSL 使用插件

plugins {
    id «plugin id» version «plugin version» [apply «false»]
}

该模块必须在构建脚本的起始位置,除非是存在buildscript {}代码块,位于它的后

旧的使用插件的方式

apply plugin: 'java'

buildscript块

当构建脚本需要使用外部库时,通过buildscript方法把已经发布的二进制插件的jar文件添加到脚本的classpath

总之,buildscript块是用来配置Gradle自己需要的仓库和依赖

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:0.4.1"
    }
}

apply plugin: "com.jfrog.bintray"

java插件

内部包含的task:

  • compileJava task that compiles all the Java source files under src/main/java
  • compileTestJava task for source files under src/test/java
  • test task that runs the tests from src/test/java
  • jar task that packages the main compiled classes and resources from src/main/resources into a single JAR named <project>-<version>.jar
  • javadoc task that generates Javadoc for the main classes

举例:添加JNI编译任务,将so文件打包

String LibPath = "src/main/c++"

task buildJNILib(type: Exec){
    workingDir "$LibPath"
    commandLine "./buildJNI.sh"
}

clean {
    delete fileTree("$LibPath") {include "**/*.so", "**/*.o"}
}


//add so file to the jar as a resource
processResources {
    dependsOn buildJNILib
    from ("$LibPath"){
        include "*.so"
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,711评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,079评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,194评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,089评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,197评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,306评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,338评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,119评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,541评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,846评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,014评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,694评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,322评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,026评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,257评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,863评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,895评论 2 351

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,644评论 18 139
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,789评论 6 342
  • Gradle是基于Groovy的动态DSL,而Groovy是基于JVM的,Groovy的语法和Java很类似。 C...
    HoooChan阅读 7,458评论 0 7
  • 参考资料:http://gold.xitu.io/post/580c85768ac247005b5472f9htt...
    zhaoyubetter阅读 10,989评论 0 6
  • 01 最近迷上了朗读者,很喜欢它第一期的主题——“遇见”: “蒹葭苍苍,白露为霜,所谓伊人,在水一方。”这是撩动心...
    林桐淮阅读 642评论 1 24