深入理解gradle中的task

深入理解gradle中的task,第1张

在之前的文章中,我们讲到了如何使用gradle创建一个简单的task,以及task之间怎么依赖,甚至使用了程序来创建task。在本文中,我们会更加深入的去了解一下gradle中的task。

定义一个task可以有很多种方式,比如下面的使用string作为task的名字:

还可以使用tasks容器来创建:

上面的例子中,我们使用tasks.create方法,将新创建的task加到tasks集合中。

我们还可以使用groovy特有的语法来定义一个task:

上面我们在创建task的时候,使用了tasks集合类来创建task。

实际上,tasks集合类是一个非常有用的工具类,我们可以使用它来做很多事情。

直接在build文件中使用tasks,实际上是引用了TaskContainer的一个实例对象。我们还可以使用 Project.getTasks() 来获取这个实例对象。

我们看下TaskContainer的定义:

从定义上,我们可以看出TaskContainer是一个task的集合和域对象的集合。

taskContainer中有四类非常重要的方法:

第一类是定位task的方法,有个分别是findByPath和getByPath。两个方法的区别就是findByPath如果没找到会返回null,而getByPath没找到的话会抛出UnknownTaskException。

看下怎么使用:

输出:

第二类是创建task的方法create,create方法有多种实现,你可以直接通过名字来创建一个task:

也可以创建特定类型的task:

还可以创建带参数的构造函数的task:

上面我们为CustomTask创建了一个带参数的构造函数,注意,这里需要带上@javax.inject.Inject注解,表示我们后面可以传递参数给这个构造函数。

我们可以这样使用:

也可以这样使用:

第三类是register,register也是用来创建新的task的,不过register执行的是延迟创建。也就是说只有当task被需要使用的时候才会被创建。

我们先看一个register方法的定义:

可以看到register返回了一个TaskProvider,有点像java多线程中的callable,当我们调用Provider.get()获取task值的时候,才会去创建这个task。

或者我们调用TaskCollection.getByName(java.lang.String)的时候也会创建对应的task。

最后一类是replace方法:

replace的作用就是创建一个新的task,并且替换掉同样名字的老的task。

task之间的依赖关系是通过task name来决定的。我们可以在同一个项目中做task之间的依赖:

也可以跨项目进行task的依赖,如果是跨项目的task依赖的话,需要制定task的路径:

或者我们可以在定义好task之后,再处理task之间的依赖关系:

还可以动态添加依赖关系:

有时候我们的task之间是有执行顺序的,我们称之为对task的排序ordering。

先看一下ordering和dependency有什么区别。dependency表示的是一种强依赖关系,如果taskA依赖于taskB,那么执行taskA的时候一定要先执行taskB。

而ordering则是一种并不太强列的顺序关系。表示taskA需要在taskB之后执行,但是taskB不执行也可以。

在gradle中有两种order:分别是must run after和should run after。

taskA.mustRunAfter(taskB)表示必须遵守的顺序关系,而taskA.shouldRunAfter(taskB)则不是必须的,在下面两种情况下可以忽略这样的顺序关系:

第一种情况是如果shouldRunAfter引入了order循环的时候。

第二种情况是如果在并行执行的情况下,task所有的依赖关系都已经满足了,那么也会忽略这个顺序。

我们看下怎么使用:

我们可以给task一些描述信息,这样我们在执行gradle tasks的时候,就可以查看到:

有时候我们需要根据build文件中的某些属性来判断是否执行特定的task,我们可以使用onlyIf :

或者我们可以抛出StopExecutionException异常,如果遇到这个异常,那么task后面的任务将不会被执行:

我们还可以启动和禁用task:

最后我们还可以让task超时,当超时的时候,执行task的线程将会被中断,并且task将会被标记为failed。

如果我们想继续执行,那么可以使用 --continue。

如果我们想要给某些task定义一些规则,那么可以使用tasks.addRule:

上我们定义了一个rule,如果taskName是以ping开头的话,那么将会输出对应的内容。

看下运行结果:

我还可以将这些rules作为依赖项引入:

和java中的finally一样,task也可以指定对应的finalize task:

finalize task是一定会被执行的,即使上面的taskX中抛出了异常。

以上就是gradle中task的详解,希望大家能够喜欢。

//task依赖:task输入输出TaskInput TaskOutput对应task的两个属性inputs,outputs.

 // wirteTask和readTask通过共同 *** 作的属性destFile关联了起来

 //gradle 规定输出属性对应的task会(生产者)先执行,输入属性对应的task后执行

ext{

    versionName='1.0.0'

    versionCode='10'

    versionInfo='App的第一个版本'

    destFile=file('realease.xml')

    if(destFile!=null &&destFile.exists()){

         destFile.createNewFile()

    }

}

###//输出文件

task writeTask{

    ####//为task指定输入

    inputs.property('versionCode',this.versionCode)

    inputs.property('versionName',this.versionName)

    inputs.property('versionInfo',this.versionInfo)

    outputs.file destFile

    doLast{

    def data=inputs.getProperties()

    File file=outputs.getFiels().getSingleFile()

    ####//将map转化为实体对象

     def versionMsg=new VersionMsg(data)

      #### //将实体数据转换成xml格式数据

     def sw=new StringWriter()

    def xmlBuilder=new MarkupBuilder(sw)

    if(file.text!=null &&file.text.size()<=0){//文件中没有内容

            xmlBuilder.releases{

                    release{

                            versionCode(versionMsg.versionCode)

                            versionName(versionMsg.versionName)

                            versionInfo(versionMsg.versionInfo)

                    }

            }

            file.withWriter {wirter->Writer.append(sw.toString())}

}else{

####//已有版本

            xmlBuilder.release{

                        versionCode(versionMsg.versionCode)

                        versionName(versionMsg.versionName)

                        versionInfo(versionMsg.versionInfo)

            }

####//将生成的xml数据插入到根节点之前

            def lines=file.readLines()

            def lengths=lines.size()-1

            file.withWriter {

                lines.eachWithIndex{ String entry,int i ->

                        if(i!=lengths){

                                it.append('\r\r\n'+sw.toString()+'\r\n')

                                it.append(lines.get(lengths))

                        }

                }

        }

    }

}

}

###//输入文件

task readTask{

    inputs.file destFile

        doLast{

            def file=inputs.files.singleFile

            println(file.text())

        }

}

class VersionMsg{

    StringversionCode

    StringversionName

    StringversionInfo

}

###//测试task

tast testTast(dependsOn:[readTask,writeTask]){

    doLast{

        println("输入输出任务结束")

    }

}

###//将wirteTask挂载到build task执行之后.

this.project.afterEvaluate {

    def buildTask=project.tasks.getByName('build')

    if(buildTask==null){

        throw GradleException("thie build task is not found")

    }

    buildTask.doLast {

        writeTask.execute()

    }

}

###//执行顺序指定mustRunAfter 强制 shouldRunAfter不强制.

task taskA{

    doLast{

    println('taskA')

    }

}

task taskB{

    mustRunAfter taskA

    doLast{

        println('taskB')

    }

}

task taskC{

    mustRunAfter taskB

    doLast{

        println('taskC')

    }

}

###//task挂载到build task构建声明周期中.

taskA.mustRunAfter variantOutput.processManifest

variantOutput.processResources.dependsOn taskA

####//这样taskA就会在variantOutput.processManifest之 后,variantOutput.processResources task之前.这两个task之间执行.

####//task类型project 提供的创建task 都是DefaultTask类型.具体有哪些类型可以使用查看

###官方文档.

https://docs.gradle.org

build.gradle//设置脚本的运行环境buildscript {//支持java 依赖库管理(maven/ivy),用于项目的依赖。repositories {mavenCentral()}//依赖包的定义。支持maven/ivy,远程,本地库,也支持单文件dependencies {classpath 'com.android.tools.build:gradle:0.4'}}//声明构建的项目类型,这里当然是android了apply plugin: 'android'//设置编译android项目的参数android {compileSdkVersion 17buildToolsVersion "17"defaultConfig {minSdkVersion 8targetSdkVersion 17}//Android默认配置sourceSets {main {manifest.srcFile 'AndroidManifest.xml'java.srcDirs = ['src']resources.srcDirs = ['src']aidl.srcDirs = ['src']renderscript.srcDirs = ['src']res.srcDirs = ['res']assets.srcDirs = ['assets']}//测试所在的路径,这里假设是tests文件夹,没有可以不写这一行instrumentTest.setRoot('tests')}//这个是解决lint报错的代码lintOptions {abortOnError false}/*** 签名设置*/signingConfigs {myConfigs {storeFile file("签名文件地址")keyAlias "..."keyPassword "..."storePassword "..."}}/*** 混淆设置*/buildTypes {release {signingConfig signingConfigs.myConfigsrunProguard trueproguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'}}/*** 渠道打包(不同包名)*/productFlavors {qqqq {applicationId = '包名'}hhhhh {applicationId='包名'}}}/*** .so文件的导入*/task copyNativeLibs(type: Copy) {from fileTree(dir: 'libs', include: 'armeabi/*.so') into 'build/lib'}tasks.withType(Compile) {options.encoding = "UTF-8"}tasks.withType(Compile) {compileTask ->compileTask.dependsOn copyNativeLibs}clean.dependsOn 'cleanCopyNativeLibs'tasks.withType(com.android.build.gradle.tasks.PackageApplication) { pkgTask ->pkgTask.jniFolders = [new File(buildDir, 'lib')]}//依赖库dependencies {compile fileTree(dir: 'libs', include: ['*.jar'])}gradle 作为构建工具,能够很方便的使用本地jar包,以下为使用的代码块。ependencies {//单文件依赖compile files('libs/android-support-v4.jar') //某个文件夹下面全部依赖compile fileTree(dir: 'libs', include: '*.jar')}android {}gradle 同时支持maven,ivy,由于ivy我没用过,所以用maven 作为例子,以下为代码块:repositories {//从中央库里面获取依赖mavenCentral() //或者使用指定的本地maven 库maven{url "file://F:/githubrepo/releases"} //或者使用指定的远程maven库maven{url "远程库地址"}}dependencies {//应用格式: packageName:artifactId:versioncompile 'com.google.android:support-v4:r13'}android {}对于项目依赖 android library的话,就不是依赖一个jar,那么简单了,在这里需要使用gradle mulit project 机制。在过去,android library并没有一个很好的包管理方式,简单来说,在gradle出现以前,官方并没有一种用于管理android library 依赖包的方式,一般我们都是直接下载别人的android library project 源码进行集成,而对于第三方的android-maven-plugin 用的是apklib 格式。而现在,官方终于推出一种android library的打包格式,扩展名为*.aar。前面提到,目前android gradle插件并不支持本地直接使用*.aar文件,不过,支持包管理库的引用方式,下面,我为大家说一下,怎么对android library 发布使用。打包android library对android library 进行打包直接在library项目下面使用gradle build 即可,然后,你就会在 build/libs 目录下看到两个*.aar文件,一个debug包用的,一个是release 下用的,看个人需求使用,这里我们用的是release 版本的 .aar 文件。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/bake/11246038.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-14
下一篇 2023-05-14

发表评论

登录后才能评论

评论列表(0条)

保存