Gradle学习7——编写和使用自定义Task

学习本系列前可以下载相关的github项目gradleLearnDemo
地址:https://github.com/sososeen09/gradleLearnDemo

自定义task包含两个组件:
1)自定义的task类,封装了逻辑行为,也被称作任务类型
2)真实的task,提供了用于配置行为的task类所暴露的属性值。Gradle把这些task称为增强的task。

可维护性是编写自定义task类的优势之一。增强的task的另一个优势是可重用性。自定义task所暴露的属性可以在构建脚本中进行单独设置。

我们还是按照之前的例子,修改配置文件中的release 参数。

1 自定义task类

前面已经提到,Gradle为构建脚本中每个简单的task都创建了一个DefaultTask类型的实例。我们现在创建一个ReleaseVersionTask,它的作用是把目标文件中的release变为true。

class ReleaseVersionTask extends DefaultTask{
  @Input Boolean release
  @OutputFile File destFile

  ReleaseVersionTask(){
    group='versioning'
    description='Makes project a release version.'
  }

  @TaskAction
  void start(){
    project.version.release=true;
    ant.propertyfile(file:destFile){
       entry(key:'release',type:'string',operation:'=',value: 'true')
    }
  }
}

通过org.gradle.api.tasks包下的注解可以用来声明输入输出属性。

task输入验证 @Input注解会在配置期间验证属性值。如果值为null,Gradle会抛出TaskValidationException异常。为了允许输入为null值,可以给它添加@Optional注解。

2 使用自定义task

我们自定义的task类是没有办法自己执行的,要使用和配置自定义task类定义的行为和属性,需要创建一个增强型的task。该task定义了它要使用的task类型,在本例中我们定义一个增强型taskmakeReleaseVersion,它使用的task类型是ReleaseVersionTask,通过为它的属性赋值来设置输入和输出。

task makeReleaseVersion(type:ReleaseVersionTask){
// 设置自定义task属性
    release = version.release
    destFile = versionFile
}

执行 gradle makeReleaseVersion 命令 ,会发现增强型的makeReleaseVersion task与之前的文章中简单的task的运行结果表现完全一致。
与简单的task实现相比,增强型task的一个巨大优势在于所暴露的属性可以被单独赋值。

比如,ProjectVersion 中的release字段名改为了prodReady,属性文件改名为 project-version.properties。
那么makeReleaseVersion task可以这样设置

task makeReleaseVersion(type:ReleaseVersionTask){
    release = version.prodReady
    destFile =file('project-version.properties')
}

3 在buildSrc目录下构建代码

我们可以把ReleaseVersionTask这个类单独放在一个Groovy文件中,这样就可以在其它地方通过导包的方式来重用这个类。
在一个项目工程当中,创建的Groovy类适合被移动到项目的buildSrc目录下。Gradle在buildSrc目录下使源文件结构标准化。Groovy代码放在src/main/groovy目录下,对于Java文件则是放置在src/main/java目录下面。位于这些目录下的文件会被自动编译,并且都加入到Gradle构建脚本的classpath中。

注意:提取一个类到Groovy文件中需要设置package,在build.gradle中或者其它地方使用这个类的时候需要导包,这一点与Java类的使用是一样的。当然了,如果这个类本身就放在build.gradle中则不需要这个过程,就像之前的例子那样。

例如 ReleaseVersionTask

package com.sososeen09.gia

import org.gradle.api.DefaultTask
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction
class ReleaseVersionTask extends DefaultTask{
...
}

Groovy文件实际放置的位置是 buildSrc/src/main/groovy/com/sososeen09/gia/ReleaseVersionTask

根据同样的方式,我们也可以把ProjectVersion这个类抽取出来。

使用的时候,在build.gradle中顶部记得导包:

import com.sososeen09.gia.ReleaseVersionTask
import com.sososeen09.gia.ProjectVersion
...

此时,执行gradle makeReleaseVersion 命令,我们就可以看到编译过程:

:buildSrc:compileJava UP-TO-DATE
:buildSrc:compileGroovy UP-TO-DATE
:buildSrc:processResources UP-TO-DATE
:buildSrc:classes UP-TO-DATE
:buildSrc:jar UP-TO-DATE
:buildSrc:assemble UP-TO-DATE
:buildSrc:compileTestJava UP-TO-DATE
:buildSrc:compileTestGroovy UP-TO-DATE
:buildSrc:processTestResources UP-TO-DATE
:buildSrc:testClasses UP-TO-DATE
:buildSrc:test UP-TO-DATE
:buildSrc:check UP-TO-DATE
:buildSrc:build UP-TO-DATE
Reading the version file
:makeReleaseVersion

记住:buildSrc 目录被视为Gradle项目的指定路径。

4 把Task编写的类编译成jar包提供给其它项目使用

我们把Groovy类放在了buildSrc目录下,虽然自定义的Task类与build.gradle分离开了,但是这些类依然只能应用到当前的项目中。如果我们想要在其它的项目中也可以使用这些Task,就需要在单独的项目中来定义,然后其它项目通过声明依赖的方式来使用。

创建一个新项目,把之前我们讲的buildSrc目录下的内容复制到这个项目中。这个时候,我们就要自己使用Groovy插件来编译这些Groovy源代码了,就像我们编译Java代码需要Java插件一样。Groovy插件是基于Java插件的。在这个项目目录下新建一个build.gradle文件,并在文件中引入Groovy Plugin。
还有一点,我们期望把这些Groovy编写的Task和其它类打包成jar文件供其它地方使用。这个时候我们就可以使用maven插件,把jar文件上传到repository中。关于如何使用maven插件上传,可以查阅相关文档,也可以看这篇 Gradle User Guide Maven Plugin。为了简单演示,打包的jar文件上传到了本地的文件系统中。最终的build.gradle文件如下:

apply plugin: 'groovy' 
apply plugin: 'maven'

version = '1.0'
group = 'com.sososeen09.gia'
archivesBaseName = 'releaseVersionTask'

repositories {
    mavenCentral()
}

dependencies {
    // 编译的时候我们需要使用Gradle中的API
    compile gradleApi()
}

uploadArchives {
    repositories {
        mavenDeployer {
            repository(url: "file:../lib")
        }
    }
}

执行gradle uploadArchives命令后就可以看到,在与当前项目同级的lib文件目录中生成了我们期望的jar文件。

下面来演示如何使用这个jar文件。我们再新建一个工程,这个工程中有一个脚本文件build.gradle和一个配置文件version.properties。
其中,build.gradle中的代码如下:

import com.sososeen09.gia.ReleaseVersionTask
import com.sososeen09.gia.ProjectVersion
buildscript {
    repositories {
        maven {
            url 'file:../lib'
        }

    }

    dependencies {
        classpath 'com.sososeen09.gia:releaseVersionTask:1.0'
    }
}

version=new ProjectVersion(0,1)

task printVersion {
  doLast{
    logger.quiet "Version: $version"
  }
}

// Project接口提供了file方法,它会创建一个相对于项目目录的java.io.File实例
ext.versionFile=file('version.properties')

task loadVersion{
    project.version=readVersion()
}

//readVersion方法,与task是不同的
ProjectVersion readVersion(){
    logger.quiet 'Reading the version file'
    if(!versionFile.exists()){
        throw new GradleException ("Required version file dose not exist:$versionFile.canonicalPath " )
    }

    //Groovy的文件实现通过添加新的方法来读取InputStream
    Properties versionProps=new Properties()
    versionFile.withInputStream{stream->
        versionProps.load(stream)
    }
    // 在Groovy中,如果return是方法中的最后一条语句的话,则可以将它省略
    new ProjectVersion(versionProps.major.toInteger(),versionProps.minor.toInteger(),versionProps.release.toBoolean())
}


task makeReleaseVersion(type:ReleaseVersionTask){
    release = version.release
    destFile = versionFile
}

version.properties中的内容如下:

major=0
minor=1
release=fasle

执行 gradle makeReleaseVersion 命令之后可以看到配置文件中release变为true。

5 总结

通过以上的介绍,我们了解了自定义Task的方式。 自定义的Task可以放置在build.gradle脚本中,也可以在当前的项目的buildSrc目录下。当然了,如果你期望你写的自定义Task可以被其它的项目中使用,那么你可以用一个单独的工程来放置自定的Task。

关于自定义Task的学习,我们也可以查看Gradle的官方Guide来查看如何自定义task

下一篇,我们开始学习Gradle中的依赖管理。

参考

    原文作者:sososeen09
    原文地址: https://www.jianshu.com/p/5a413815a7ae
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞