1 了解task
task是gardle中最小的任务单元,任务之间可以进行复杂的操作(如动态创建任务,多任务间依赖调用等等)。gradle的执行其实就是由各种任务组合执行,来对项目进行构建的。
使用gradlew help命令,任何gradle项目都有一个该task,可以执行此命令观察taks执行的流程是否如预期。 可以使用工具查看,还可以通过 gradlew tasks 命令查看可运行任务。
使用gradlew tasks --all 命令查看所有任务。
使用gradlew A B 命令表示执行任务A和B,支持驼峰简写。
2 自定义Task
在build.gradle中自定义任务:
task <任务名>{ .. },在Gradle5.x以上已经删除<<操作符这种写法。
{ ... }执行的是配置阶段的代码,执行阶段要处理的逻辑需要调用doFirst、doLast方法,在闭包中实现。doFirst{}表示任务执行开始时调用的方法,doLast{}表示任务执行结束调用的方法。
task A(dependsOn:[B]){ .. } 表示任务A依赖于任务B,那么B执行在A之前。
自定义的任务默认分组到other中。
(1)自定义类继承DefaultTask
在方法上使用@TaskAction注解,表示任务运行时调用的方法。 使用@Input表示对任务的输入参数。 使用@OutputFile表示任务输出文件。 使用inputs,outputs直接设置任务输入/输出项。 一个任务的输出项可以作为另一个任务的输入项 (隐式依赖关系)。
class ZipTask extends DefaultTask {
@Input
@Optional
// 表示可选
String from
File out
ZipTask() {
outputs.upToDateWhen {
false// 增量构建,每次都会开启,不会跳过任务,构造函数中调用(如果没有更新就不会去构建,设置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') //输入文件的路径,这种写法不需要使用 @Input注解
outputs.file file('test.txt') //输出的路径
}
使用@TaskAction注解 相当于main()函数,在调用task ,则会自动调用内部有该注解的方法。
(2)下面使用task 完成以下任务
使用自定义任务,实现zip打包packageDebug输出的内容
这里使用到内部的task Zip ,如何使用这个task 如下
task zip(type: Zip) {
archiveName "outputs.zip"// 输出的文件名字
destinationDir file("${buildDir}/custom")// 输出的文件存放的文件夹
from "${buildDir}/outputs"// 输入的文件
}
好,现在我们是实现任务。
这里我们需要使用到afterEvaluate, afterEvaluate是一个钩子函数 会让闭包里面的内容 在编译结果后才会执行,看具体实现
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
}
}
}
Gradle内部的其他钩子函数。
gradle.beforeProject {
println "gradle.beforeProject"
}
gradle.afterProject {
println "gradle.afterProject"
}
gradle.taskGraph.whenReady {
println "gradle.taskGraph.whenReady"
}
beforeEvaluate {
// 在root无效
println "beforeEvaluate"
}
afterEvaluate {
println "afterEvaluate"
}
为什么会需要到这些钩子函数,这里我们要了解下gradle的运行阶段,如下图
1 初始化阶段 :
如 setting.gradle 的执行
2 配置阶段(最重要的阶段):
buildGradle 内部创建的是project,所以默认作用域是project.
gradle.beforeProject()这些gradle引用的每一个工程在配置阶段都会去调用这些方法
project.beforeEvaluate()方法 只会在当前工程配置阶段会被调用。由于作用域是project所以project可以去省略。
给gradle 设置监听
gradle.addProjectEvaluationListener(new ProjectEvaluationListener() {
@Override
void beforeEvaluate(Project project) {
println "beforeEvaluate"
}
@Override
void afterEvaluate(Project project, ProjectState state) {
println "afterEvaluate"
}
})
gradle.addBuildListener(new BuildListener() {
@Override
void buildStarted(Gradle gradle) {
}
@Override
void settingsEvaluated(Settings settings) {
}
@Override
void projectsLoaded(Gradle gradle) {
}
@Override
void projectsEvaluated(Gradle gradle) {
}
@Override
void buildFinished(BuildResult result) {
}
})
3执行阶段
3 脚本二进制插件(通过实现Plugin)
class MyPlugin implements Plugin<Project> {
@Override
void apply(Project target) {
println "MyPlugin apply"
target.afterEvaluate {
println target.tasks.getByName("packageDebug")
target.task(type: Zip, "zipDebug") {
archiveName "outputs4.zip"// 输出的文件名字
destinationDir target.file("${target.buildDir}/custom")// 输出的文件存放的文件夹
from target.tasks.getByName("packageDebug").outputs.files// 输入的文件
target.tasks.getByName("packageDebug").outputs.files.each {
println it
}
}
}
}
}
apply 为入口函数跟,内部实现跟上面。当然这块代码也是可以写在java 工程中的
public class MyPlugin2 implements Plugin<Project> {
@Override
public void apply(Project target) {
target.afterEvaluate(project -> {
System.out.println(project.getTasks().getByName("packageDebug"));
Map<String, Class<?>> type = new HashMap<>();
type.put("type", Zip.class);
Zip zipDebug2 = (Zip) target.task(type, "zipDebug2");
zipDebug2.setArchiveName("outputs5.zip");
zipDebug2.setDestinationDir(new File(target.getBuildDir().getAbsolutePath()+"/custom"));
zipDebug2.from(target.getTasks().getByName("packageDebug").getOutputs().getFiles());
});
}
}
自定义Plugin结束后,只需要在buildgradle中进行配置
apply plugin: MyPlugin
apply plugin: MyPlugin2