Android Gradle 自定义Task 详解
转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/76408024
本文出自【赵彦军的博客】
一:Gradle 是什么
- Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化构建工具。
- 它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,抛弃了基于XML的各种繁琐配置。面向Java应用为主。
- 当前其支持的语言限于Java、Groovy、Kotlin和Scala,计划未来将支持更多的语言。基于 groovy 脚本构建,其 build 脚本使用 groovy 语言编写。
关于 gradle 相关运用,可以移步 :Android Gradle使用总结
二:groovy 是什么
Groovy是一种动态语言,它和Java类似(算是Java的升级版,但是又具备脚本语言的特点),都在Java虚拟机中运行。当运行Groovy脚本时它会先被编译成Java类字节码,然后通过JVM虚拟机执行这个Java字节码类。
关于 groovy 相关知识,移步到这里:Groovy 使用完全解析
三:Gradle 的 Project 和 Tasks
每次构建(build)至少由一个project构成,一个project 由一到多个task构成。每个task代表了构建过程当中的一个原子性操作,比如编译,打包,生成javadoc,发布等等这些操作。
gradle : 一个 project 包含多个 task,一个 task 包含多个 Action
project
-- task1 (Action1、Action2...)
-- task2 (Action1、Action2...)
-- ...
四:自定义 Task
- 格式:
task 任务的名字 {
//do some things
}
- 例子
build.gradle
//定义 task , 名字 hello
task hello{
println "hello world"
}
//定义 task,名字 hello
task(hello2){
println "hello world2"
}
//定义 task,名字 hello3
task ('hello3'){
println "hello world3"
}
- 在终端运行 gradle 命令
//执行 hello task
gradlew hello
//执行 hello2 task
gradlew hello2
//执行 hello3 task
gradlew hello3
五:创建Action
在上面的举例中,是一个非正式的 task , 说非正式是因为创建的 task 里面没有 action 。task 本质上又是由一组被顺序执行的 Action 对象构成,Action其实是一段代码块,类似于Java中的方法。
创建 Action 相关 API
//在Action 队列头部添加Action
Task doFirst(Action<? super Task> action);
Task doFirst(Closure action);
//在Action 队列尾部添加Action
Task doLast(Action<? super Task> action);
Task doLast(Closure action);
//已经过时了,建议用 doLast 代替
Task leftShift(Closure action);
//删除所有的Action
Task deleteAllActions();
小例子
build.gradle
//创建一个名字为hello的 task
task hello {
//创建一个 Action , 添加到 Action 列表的头部
doFirst(new Action<Task>() {
@Override
void execute(Task task) {
println "action1++++++++++"
}
})
//创建一个 Action , 添加到 Action 列表的头部
doFirst {
println "action2++++++++++"
}
}
在 Action 列表中添加了 两个 Action , Action 列表如下图所示:
运行 hello task : gradle hello
运行结果:
action2++++++++++
action1++++++++++
leftShift 说明
leftShift 的作用和 doLast 一样,在action 列表尾部添加一个Action,只不过现在过时了,官方建议用 doLast 代替。下面举个小例子:
build.gradle
task hello {
//在 Action 列表尾部添加一个 Action
leftShift {
println "+++++"
}
}
leftShift 还有一种简洁写法,用 <<
代替, 如下所示:
build.gradle
task hello <<{
//在 Action 列表尾部添加一个 Action
println "+++++"
}
那么问题来了,task 中的 Action 在什么时候执行?
六:Gradle 生命周期
1.初始化阶段
会去读取根工程中 setting.gradle 中的 include 信息,决定有哪几个工程加入构建,创建 project 实例,比如下面有三个工程: include ':app', ':lib1', ':lib2 。
2.配置阶段
会去执行所有工程的 build.gradle 脚本,配置 project对象,一个对象由多个任务组成,
此阶段也会去创建、配置task及相关信息。
3.运行阶段
根据gradle命令传递过来的task名称,执行相关依赖任务。Task 的 Action 会在这个阶段执行。
七:创建 Task 的另外一种方式
在上面讲解了创建 task 的基本方式,其实 gradle api 给我们提供了其他的方式创建 task ,下面讲解其他两种方式。
- tasks
build.gradle
//创建 hello2 task
tasks.create("hello2"){
doFirst {
println "hello2+++++"
}
}
- 自定义 DefaultTask 子类
class MyTask extends DefaultTask {
@TaskAction
void action(){
println "action1+++++"
}
}
//创建 hello3 task
task hello3 (type: MyTask){
doLast{
println "action2+++++"
}
}
运行 hello3 task: gradlew hello3
输出
action1+++++
action2+++++
八: Task 依赖
1、dependsOn
build.gradle
task task1 << {
println "我是task1----"
}
task task2 << {
println "我是task2----"
}
//task2 依赖 task1, 执行task2之前先执行task1
task2.dependsOn task1
执行 task2
gradlew task2
执行效果
我是task1----
我是task2----
2、mustRunAfter
两个 task 依赖
task task1 << {
println "我是task1----"
}
task task2 << {
println "我是task2----"
}
//task2 运行之前先运行task1
task2.mustRunAfter task1
- 执行 task1 : gradlew task1
我是task1----
- 执行 task2 : gradlew task2
我是task2----
- 同时执行 task1、task2 : gradlew task1 task2
我是task1----
我是task2----
三个 task 相互依赖
build.gradle
task task1 << {
println "我是task1----"
}
task task2 << {
println "我是task2----"
}
task task3 << {
println "我是task3----"
}
task2.mustRunAfter task1
task3.mustRunAfter task1
- 执行 gradlew task1 task2 task3
我是task1----
我是task2----
我是task3----
- 执行 gradlew task1 task3 task2
我是task1----
我是task3----
我是task1----
在出现语法矛盾的情况下,依赖关系形成闭环,编译器会报错
task1.mustRunAfter task2
task2.mustRunAfter task1
3、shouldRunAfter
形成依赖关系可有可无。
build.gradle
task task1 << {
println "我是task1----"
}
task task2 << {
println "我是task2----"
}
task1.shouldRunAfter task2
运行: gradlew task1 task2
我是task2----
我是task1----
在出现语法矛盾的情况下,依赖关系形成闭环,会自动打破闭环。不会报错
九:系统默认 task
gradle 默认提供了很多 task 给我们使用,比如 copy、delete
1、copy
build.gradle
task 任务的名字 (type: Copy) {
//action
}
- Api 介绍
//数据源目录,多个目录
public AbstractCopyTask from(Object... sourcePaths)
//目标目录,单一
public AbstractCopyTask into(Object destDir)
//过滤文件 包含
public AbstractCopyTask include(String... includes)
//过滤文件 排除
public AbstractCopyTask exclude(String... excludes)
//重新命名,老名字 新名字
public AbstractCopyTask rename(String sourceRegEx, String replaceWith)
//删除文件 Project 接口
boolean delete(Object... paths);
小例子:
- 复制图片:单一数据源
task copyImage(type: Copy) {
from 'C:\\Users\\yiba_zyj\\Desktop\\gradle\\copy'
into 'C:\\Users\\yiba_zyj\\Desktop'
}
- 复制图片:多个数据源
task copyImage(type: Copy) {
from 'C:\\Users\\yiba_zyj\\Desktop\\gradle\\copy' ,
'C:\\Users\\yiba_zyj\\Desktop\\gradle\\copy'
into 'C:\\Users\\yiba_zyj\\Desktop'
}
- 复制图片:过滤文件
只会复制后缀为 .jpg 的文件
task copyImage(type: Copy) {
from 'C:\\Users\\yiba_zyj\\Desktop\\gradle\\copy'
into 'C:\\Users\\yiba_zyj\\Desktop'
include "*.jpg"
}
- 复制文件:过滤文件,重命名
task copyImage(type: Copy) {
from 'C:\\Users\\yiba_zyj\\Desktop\\gradle\\copy'
into 'C:\\Users\\yiba_zyj\\Desktop'
include "*.jpg"
exclude "image1.jpg"
rename("image2.jpg","123.jpg")
}
文件覆盖规则
相同文件覆盖
Copy 类的继承图
Copy (类)
- AbstractCopyTask (抽象类) (from、 into、 include、rename)
-ConventionTask(抽象类)
- DefaultTask (类)
- AbstractTask (抽象类)
- TaskInternal (接口)
- Task(接口)
-Comparable<Task>, ExtensionAware(接口)
-Project(接口) (delete 方法)
2、Delete
- 删除 Android 更目录的aaa 文件
build.gradle
task deleteFile(type: Delete) {
//删除Android 更目录的aaa 文件
delete '../aaa'
}
- 删除桌面上的文件
build.gradle
task deleteFile(type: Delete) {
//删除系统桌面 delete
delete "C:\\Users\\yiba_zyj\\Desktop\\gradle\\delete"
}
十:小技巧
1、自定义 task 的名字用驼峰命名法
build.gradle
task deleteFile{
//do some things
}
运行
gradlew dF 等价 gradlew deleteFile
打包时候运行 gradlew assembleRelease
,可以简写成 gradlew aR
2、常见的 gradlew 命令
查看项目所有默认自带的 task,不包括自定义 task
gradlew tasks
查看所有 task (默认 task + 自定义task)
gradlew tasks --all
查看某个 task 的相关信息,这些结果包含了任务的路径、类型以及描述信息等
gradlew help --task taskName
查看 gradle 版本
gradlew -version
3、给task 添加描述 description
task task1 << {
description = "这是一段描述信息"
println "我是task1----"
}
十一:Gradle 环境变量配置
在上面的介绍中,运行 task 的方式是用 gradlew
, 那我们怎么用 gradle
。如果在终端运行 gradle
就会提示 gradle 不是内部或外部命令,也不是可运行的程序或批处理文件。
'gradle' 不是内部或外部命令,也不是可运行的程序或批处理文件。
官网下载:http://services.gradle.org/distributions/
下载完成后,我将压缩包解压放在 d 盘的 soft 目录中。
环境变量
- GRADLE_HOME
D:\soft\gradle-4.3-all
- Path
D:\soft\gradle-4.3-all\gradle-4.3\bin
参考资料
个人微信号:zhaoyanjun125 , 欢迎关注
Android Gradle 自定义Task 详解的更多相关文章
- Gradle技术之四 - Gradle的Task详解
1 Gradle的Task详解 1 Task定义和配置 2 Task的执行 3 Task的依赖和执行顺序 4 Task类型 5 Task结合gradle的生命周期 6 Task实战 1.1 Task定 ...
- Android 自定义 View 详解
View 的绘制系列文章: Android View 绘制流程之 DecorView 与 ViewRootImpl Android View 的绘制流程之 Measure 过程详解 (一) Andro ...
- 【转载】Android Studio Service AIDL 详解
公司产品之前IM这块存在很多问题,消息到达率低,加上协议上有些问题,丢消息频繁,所以需要重构IM,AIDL不能解决以上问题.好吧!那AIDL可以解决什么问题?什么是AIDL? 什么是AIDL? AID ...
- Android开发之InstanceState详解
Android开发之InstanceState详解 本文介绍Android中关于Activity的两个神秘方法:onSaveInstanceState() 和 onRestoreInstanceS ...
- 给 Android 开发者的 RxJava 详解
我从去年开始使用 RxJava ,到现在一年多了.今年加入了 Flipboard 后,看到 Flipboard 的 Android 项目也在使用 RxJava ,并且使用的场景越来越多 .而最近这几个 ...
- Android开发之InstanceState详解(转)---利用其保存Activity状态
Android开发之InstanceState详解 本文介绍Android中关于Activity的两个神秘方法:onSaveInstanceState() 和 onRestoreInstanceS ...
- android ------- 开发者的 RxJava 详解
在正文开始之前的最后,放上 GitHub 链接和引入依赖的 gradle 代码: Github: https://github.com/ReactiveX/RxJava https://github. ...
- 转:给 Android 开发者的 RxJava 详解
转自: http://gank.io/post/560e15be2dca930e00da1083 评注:多图解析,但是我还是未看懂. 前言 我从去年开始使用 RxJava ,到现在一年多了.今年加入 ...
- ANDROID L——Material Design详解(UI控件)
转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! Android L: Google已经确认Android L就是Android Lolli ...
随机推荐
- 菜鸟玩云计算之十四:克隆虚拟机及ssh登录的问题
菜鸟玩云计算之十四:克隆虚拟机及ssh登录的问题 今天早上,我的Ubuntu12.04.3LTS Desktop提示升级,升级. 从vm-ubuntu12.04克隆出虚拟机vm-thrift: $ s ...
- MiseringThread.java 解析页面线程
MiseringThread.java 解析页面线程 http://injavawetrust.iteye.com package com.iteye.injavawetrust.miner; imp ...
- java的hashcode(结合hashset讲解)
equals()跟hashcode()都可以用来比较对象.hashcode通过不同对象有不同的散列码来比较两个对象. hashcode方法把对象放到一个对象容器进行查找,算法好坏直接影响容器的存取效率 ...
- Vi/Vim 替换使用方法
vi/vim 中可以使用 :s 命令来替换字符串.该命令有很多种不同细节使用方法,可以实现复杂的功能,记录几种在此,方便以后查询. :s/vivian/sky/ 替换当前行第一个 vivian 为 s ...
- sublimeText3使用记录
sublime确实是神器,最近学习了一下,做个记录 1.下载 http://www.sublimetext.com/3 选择对应的版本安装即可(我的是win10 64位机) 2.个人配置 2.1.默认 ...
- 《java入门第一季》之面向对象(匿名对象)
/* 匿名对象:就是没有名字的对象. 匿名对象的应用场景: A:调用方法,仅仅只调用一次的时候. 注意:调用多次的时候,不适合. 匿名对象调用完毕就是垃圾.可以被垃圾回收器回收,释放了系统资源. B: ...
- Android For JNI(一)——JNI的概念以及C语言开发工具dev-c++,编写你的第一个C语言程序,使用C启动JAVA程序
Android For JNI(一)--JNI的概念以及C语言开发工具dev-c++,编写你的第一个C语言程序 当你的Android之旅一步步的深入的时候,你其实会发现,很多东西都必须去和framew ...
- 网络I/O中的同步、异步、阻塞和非阻塞概念
在学习网络编程过程中,经常会把这几个概念搞混淆. 同步I/O与异步I/O区别 我们先来看一下操作I/O时涉及的对象和步骤(这里我们以read为例): 这里会涉及到两个系统对象,一个是调用这个I/O的应 ...
- Struts2技术内幕 读书笔记二 web开发的基本模式
最佳实践 在讨论基本模式之前,我们先说说一个词:最佳实践 任何程序的编写都得遵循一个特定的规范.这种规范有约定俗称的例如:包名全小写,类名每个单词第一个字母大写等等等等;另外还有一些需要我们严格遵守的 ...
- Swift之GCD使用指南1
Grand Central Dispatch(GCD)是异步执行任务的技术之一.一般将应用程序中记述的线程管理用的代码在系统级中实现.开发者只需要定义想执行的任务并追加到适当的Dispatch Que ...