Gradle API 以及Task

Gradle 编程框架

1.groovy语法

2.Build Script Block

3.gradle api

前言

1.灵活性上: ANT和Maven 不能在构建过程中,做自定义操作.

2.颗粒度: gradle 代码开源, 根据task编译,可读,可改

3.扩展性 : 可以在gradle脚本中 可以自定义插件.自定义task

4.兼容性 : gralde代码中, 可以继续依赖 maven等框架

执行过程

initliazation 解析整个工程的所有project, 构建project对象

configuration 解析project对象中的task, 构建好 所欲task 的拓扑图

execution 执行具体的task 以及依赖

project API

project 树状结构

rootProject 根节点

parentProject 父节点

this.project 当前节点

subProject 子节点

project 中常用api介绍

//给某个project设置属性
project("module-user"){Project project ->


}


//可以给所有子项目 设置 自动推送到maven仓库
subprojects {Project project->
    if(project.plugins.hasPlugin('com.android.library')){
        apply from:"../publishToMaven.gradle"
    }
}


//可以给所有子项目 设置 自动推送到maven仓库
subprojects {Project project->
    if(project.plugins.hasPlugin('com.android.library')){
        apply from:"../publishToMaven.gradle"
    }
}

//配置所有项目的属性
allprojects {Project project->
    group "com.ccj"
    
}

project的属性API

默认属性

为啥 配置文件必须叫build.gradle?

因为project中 第一个属性就是 ,默认的文件名,不可修改

    /**
     * The default project build file name.
     */
    public static final String DEFAULT_BUILD_FILE = "build.gradle";

    /**
     * The hierarchy separator for project and task path names.
     */
    public static final String PATH_SEPARATOR = ":";

    /**
     * The default build directory name.
     */
    public static final String DEFAULT_BUILD_DIR_NAME = "build";

    public static final String GRADLE_PROPERTIES = "gradle.properties";

    public static final String SYSTEM_PROP_PREFIX = "systemProp";

    public static final String DEFAULT_VERSION = "unspecified";

    public static final String DEFAULT_STATUS = "release";

扩展属性

1.在rootProject或者当前project中,使用ext字段,来自定义属性

ext{
    compileSdkVersion 25
       
}

在项目中可以用这个字段来使用


android {
    //两种方式, rootProject. compileSdkVersion  也可以直接用complieVersion
    //因为, project之间有继承关系, 如果父类有自定义的属性,那么结构树下的所有子project都会有这个属性.
    compileSdkVersion compileSdkVersion //rootProject. compileSdkVersion

1.使用 apply from '配置路径'

首先,在根节点 新建一个config.gradle .然后在各个子 项目中, 直接使用apply from: this.file("config.gradle") 即可.


/*
* 在rootProject中 引用
* apply from: this.file("config.gradle")
*
* 在子project中 这样引用 rootProject.ext.android.XXX 即可
* */
ext{
    android=[
            compileSdkVersion: 26,
            buildToolsVersion: "26.0.1",
            minSdkVersion: 21,
            targetSdkVersion: 26,
            versionCode: 1,
            versionName: "1.0"

    ]
    dependencies=[
            compile:'com.android.support:support-v4:21.0.3',
            compile: (project(':CommonSDK')) { exclude group: "com.android.support" },
            provided: fileTree(dir: 'src/android5/libs', include: ['*.jar']),
            provided: project(':main-host')
    ]
}
依赖相关
buildscript {ScriptHandler scriptHandler->

    //配置工程的仓库地址  //为啥不用闭包参数就可以调用, 因为闭包的delegate设置的就是repositoryHandler
    scriptHandler.repositories {RepositoryHandler repositoryHandler ->
        repositoryHandler.jcenter()
       // repositoryHandler.mavenCentral()//这也是为啥gradle能兼容maven的原因
       // google()
       //repositoryHandler.flatDir("这里可以直接依赖项目")

       /* repositoryHandler.maven {   //可以添加自己的
            name "myMaven"
            url 'http://localhost:8081:/nexus/respositoeries'
            getCredentials{
                username = 'amdin'
                password = '123'
            }
        }*/

    }

    //配置工程中插件的依赖地址
    scriptHandler.dependencies { DependencyHandler dependencyHandler ->
            dependencyHandler. classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'

    
    }
    

依赖冲突


    compile "com.android.support:support-v4:${SUPPORT_LIB_VERSION}"{
        exclude module:'support-v4'// 排除依赖
        transitive false //禁止传递依赖
        changing =true //每次都会从服务器拉取
    }
    //compile //资源和类,都会被打进jar, 或者aar包中
    //provided //编译的时候会引入,但是不会将这个包打入.
    // 比如1.类的生成器(只在编译器起作用,不在运行时起作用).
    //    2. 如果当前工程是类库,而且该工程的类库和 主工程有重复,则可以用这种方式.


执行外部命令

可以执行 bash等命令

task(name:'apkcopy'){

    doLast{
        //执行外部的命令,比如bash命令
        //将 apk copy到制定目录
        def sourcePath =this.buildDir.path+"/outputs/apk"
        def desationPath="/Users/chenchangjun/Downloads/"

        def copycommand ="mv -f ${sourcePath} ${desationPath}"

        exec {ExecSpec execSpec->

            try {
                execSpec.executable('bash')
                args('-c',copycommand)
                println 'copycommand is execute success!'
            }catch (GradleException e){
                println 'copycommand is execute failed'+e.printStackTrace()


            }

        }

    }


}

Task

image.png

//直接通过task函数去创建
//group 组名,可以在右侧gralde面板中 见到group分组
//description 就是描述,类似于注释
task helloTask(group:'ccj',description:'task helloTask'){
    println 'i am helloTask'

}

//容器创建
this.tasks.create(name:'hello2'){
    setGroup('ccj')
    setDescription('task hello')
    println "i am hello2 "

}

//为什么 只执行了 helloTask,却连hello2也会被执行呢?
// 因为上述task 是在 配置阶段进行的, 而配置阶段,gralde中的代码都会执行.


//task 的方法

task helloExecuteTask(group:'ccj',description:'task helloExecuteTask'){
    println 'i am helloExecuteTask'
    doFirst{
        println 'i am helloExecuteTask>>doFirst'

    }
    doLast{
        println 'i am helloExecuteTask>>doLast'
    }

}


helloExecuteTask.doFirst{
    println 'i am helloExecuteTask.doFirst'

}

//计算build的执行时间

def startBuildTime,endBuildTime

this.afterEvaluate {Project project->
    //保证要找的task 已经配置完毕
    def preBuildTask=project.tasks.getByName('preBuild')
    preBuildTask.doFirst {
        println 'preBuildTask.doFirst>>>>>>>>'
        startBuildTime=System.currentTimeMillis()

    }
    def buildTask=project.tasks.getByName('build')
    buildTask.doLast {
        endBuildTime=System.currentTimeMillis()
        println "the buildTask time is >>>>>>>>>>>${endBuildTime-startBuildTime}"

    }
}

task 依赖dependsOn

//task 依赖

task taskDepend1{

    doLast{
        println "taskDepend1"
    }


}

task taskDepend2{

    doLast{
        println "taskDepend2"
    }


}


task taskDepend3(dependsOn:[taskDepend1,taskDepend2]){

    doLast{
        println "taskDepend3"
    }


}


task handleFile {

    def srcFile = file('testdepends.xml')
    def desFile = new File(this.buildDir.path + "generated/release/result.text")
    println "build文件目录:"+this.buildDir.path
    doLast {

        println '开始解析对应的xml文件'

        if (!desFile.exists()) {
            desFile.createNewFile()
        }
        def releases = new XmlParser().parse(srcFile) //得到根节点
        releases.children().each { Node node ->

            def value = node.text()
            println value

            desFile.withWriter { writer ->
                writer.write(value)

            }

        }

    }


}

task testHandleFile(dependsOn: handleFile) {
    println '解析完成'

}


Task 传递

image.png

/*TaskOutputs outputs
TaskInputs taskInputs*/

task must1{

    doLast{
        println 'must1.doLast'

    }
}


task must2{
    mustRunAfter must1
    //shouldRunAfter
    doLast{
        println 'must2.doLast'

    }
}

task must3{
    mustRunAfter must2
    doLast{
        println 'must3.doLast'

    }
}

/*
*
* gradle must2 must3 must1
*
> Task :zdm_router_register:must1
must1.doLast

> Task :zdm_router_register:must2
must2.doLast

> Task :zdm_router_register:must3
must3.doLast

*/


task的方法

gradle 约定大于配置, 有很多默认的配置,不改变也会安装默认的执行

Settings即 settings.gradle gralde初始化会调用.

SourceSet

可以在android{}闭包下这样写

 sourceSets{
       main{
          // jniLibs.src=['libs'] //修改so库的存放位置
            res.srcDirs=['src/main/res', //可以用来对资源进行分包,以后便于维护,超级好用
                    'src/main/res-ad',
                    'src/main/res-player'
            ]
       }
    }

也可以在project根节点下这样写

this.android.sourceSets{
    main{
        // jniLibs.src=['libs'] //修改so库的存放位置
        res.srcDirs=['src/main/res', //可以用来对资源进行分包,以后便于维护
                     'src/main/res-ad',
                     'src/main/res-player'
        ]
    }
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容