• gradle学习之旅(六) 使用task(下)


    增量式构建

    • gradle判断task是否改变过的依据是:这个task的inputs和outputs属性组成的集合。当一个task链被执行时,如果其中某一个task的inputs和outputs没有发生改变,则认为该task是最新的,该task将被跳过,在执行链输出中可以看到该task被标为UP-TO-DATE,下图为Task中的imputs和outputs属性
    • inputs 属性应该被赋值为 一个目录、一个或多个文件、或是一个任意属性
    • outputs 应该被赋值为一个或多个目录或者一个或多个文件

    那么增量式构建使用场景是怎样的呢?下面是一个例子:

    • 例子
      假设一个task,makeReleaseVersion,在项目发布部署之前要修改项目版本的release值为true:
    task makeReleaseVersion(group: 'versioning' , description: 'Makes Project a release version.') << {
    	version.release = true
    	ant.propertyfile(file: versionFile){
    		entry(key: 'release', type: 'string',operation: '=',value:'true')//利用ant task的propertyfile提供的便利方式来修改属性文件
    	}
    }
    

    但是意外发生了,在自动化发布的过程中无法连上服务器,在修复故障后,重新运行自动化发布的任务,因为部署任务依赖于修改版本号任务,所以makeReleaseVersion任务会再次被运行,即使版本号已经在上次运行过程中被修改。
    为解决这一问题,需要采用gradle提供的增量式构建特性,为该task的inputs和outputs赋值:

    task makeReleaseVersion(group: 'versioning' , description: 'Makes Project a release version.')  {
    	inputs.property ('release',version.release)  
    	outputs.file versionFile //由于该任务会修改版本文件,所以它被声明为outputs
    	doLast{
    		version.release = true
    		ant.propertyfile(file: versionFile){
    			entry(key: 'release', type: 'string',operation: '=',value:'true')//利用ant task的propertyfile提供的便利方式来修改属性文件
    		}
    	}
    }
    

    这样就实现了增量式构建

    • task的inputs和outputs的执行
      确保inputs和outputs的值在配置阶段是可访问的,因为它们在配置阶段被执行。如果要通过编程获得输出,则可以通过upToDateWhen(Closure var1)方法来实现,与常规的inputs和outputs的set方法比,这个方法是在执行阶段执行的,如果闭包返回true,则这个task被认为是最新的。

    自定义task

    在gradle中,默认Task的实现类为DefaultTask,而DefaultTask中空无一物,全部继承自AbstractTask。当构建task的动作逻辑变得相当复杂时,必然会产生结构化task代码的需求,这时就可以实现自定义的Task实现类。
    下面将makeReleaseVersion封装为ReleaseVersionTask的自定义Task

    class ReleaseVersionTask extends DefaultTask {
    	@Input Boolean release //通过org.gradle.api.tasks包下的注解来声明输入输出
    	@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')//利用ant task的propertyfile提供的便利方式来修改属性文件
    		}
    	}
    }
    

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

    • 使用方法
    task makeReleaseVersion(type: ReleaseVersionTask) {
    	release = version.release
    	destFile = versionFile
    }
    

    Gradle的内置task类型

    在Gradle DSL指南中可以找到完整的task参考
    下面用一个使用类型为内置的task类型Zip的task

    task createDistribution(type: Zip, dependsOn: makeReleaseVersion){
    	from war.outputs.files //依赖推断
    	
    	from(sourceSets*.allSource){
    		into 'src'
    	}
    	
    	from(rootDir){
    		include versionFile.name
    	}
    }
    
    • task依赖推断
      在上面的createDistribution task中声明了依赖的task,但是一些task并不直接依赖其他task,比如createDistribution对于war。通过使用一个task的输出作为另一个task的输入,Gradle就可以推断出依赖关系,所依赖的task会自动运行。

    task规则

    Gradle引入task规则的概念,就是根据task名称模式执行特定的逻辑。

    • task规则命名模式
      task名称的静态部分和一个占位符组成一个task规则名字,例如increment<Classifier>Version。java插件的clean任务便利用了task规则,clean<TaskName>用来删除指定task的输出。
    • 声明task规则
      • 首先,获得对TaskContainer的引用,该引用为tasks
      • 然后,调用addRule(String,Closure)方法,第一个参数提供了描述信息(比如,task命名模式),第二个参数声明了要执行的闭包来应用规则。
      • 例如这样:
      tasks.addRule("Pattern: increment<Classifier>Version - Increments the project version classifier."){
      	String taskName ->
      	if(taskName.startsWith('increment') && taskName.endWith('Version')){
      		task(taskName)<<{
      			String classifier = (taskName - 'increment'- 'Version').toLowerCase()
      			//接下来便是分支判断代码
      		}
      	}
      }
      
    • task规则不能像处理任何其它简单的task或增强的task一样被独立分组,task规则会显示在Rules组下。

    构建源代码目录buildSrc

    事实上在build.gradle文件中不适合写面向对象的代码,所以应该把之前的POJO类和自定义task类像项目源代码一样组织起来,类似于java源代码放在src/main/java目录下、Groovy代码放在src/main/groovy目录下,buildSrc用于组织构建代码源文件。构建代码包可以放在buildSrc/src/main/groovy或buildSrc/src/main/java下,这样还方便写构建代码的单元测试代码。

  • 相关阅读:
    iphone/iOS 访问本地数据库sqlite3
    SQLITE3 --详解
    iOS使用MD5
    ASIHTTPRequest实现断点续传
    ios开发
    iOS 5的文件存储策略应对
    由ASIHttpRequest里的block引发的思考
    Blocks编程要点
    [Cocoa]深入浅出Cocoa多线程编程之 block 与 dispatch quene
    ASIHTTPRequest 问题总结
  • 原文地址:https://www.cnblogs.com/Theshy/p/7891485.html
Copyright © 2020-2023  润新知