Gradle插件相关知识

Gradle插件

插件工程结构

Gradle插件的工程结构如下图所示:

Gradle插件相关知识_第1张图片
Paste_Image.png

这个工程既可以作为单独的工程,也可以作为子工程存在,工程目录分为groovy和resources两个目录,分别存放插件groovy文件和配置文件。

build.gradle

Gradle插件相关知识_第2张图片
Paste_Image.png

还需要添加以下配置保证插件在不同版本的java平台正常运行

Gradle插件相关知识_第3张图片
Paste_Image.png

插件代码

声明Groovy文件,implements Plugin,在void apply(Project project) 方法中实现插件代码。在resources目录下META-INF.gradle-plugins创建一个properties文件,将Groovy文件的包名加类名声明在properties文件中,例如com.husor.android.makechannel.properties文件中:

implementation-class=com.husor.android.makechannel.MakeChannelPlugin

这就代表插件名为com.husor.android.makechannel,具体实现内容在MakeChannelPlugin文件中。

在apply方法中传入了project对象,表示我可以使用project对象的任意api,project对象可以获取到任意的工程中的文件、任务,那么能做的事情就很多了,比如复制文件、上传文件,android插件的打包过程就是通过android_sdk/tools下的工具,对当前工程中的各种文件进行编译、签名、对齐、打包等操作的。希望下一篇文章,可以学习一下安卓的打包过程。

插件发布

Gradle插件相关知识_第4张图片
Paste_Image.png

上传到本地testRepo目录下的插件包地址为com.beibei.android:makechannel:1.0.0-SNAPSHOT

上传到maven服务的插件包地址为com.beibei.android:makechannel:1.0.0

注意上传到本地的artifactId取决于project的name,而当前name为makechannel,上传到maven库的artifactId取决于声明

插件使用

Gradle插件相关知识_第5张图片
Paste_Image.png

Groovy

在学习Gradle之前,首先要了解Groovy,Groovy是一种脚本语言,基于Java又拓展了java的特性,欢迎参考官方文档 http://www.groovy-lang.org/documentation.html ,深入学习起来还是有一大片天地的,接下来我简单讲讲我理解的一些基本特性。

首先看一段代码:

task testGroovy << {
    def var1 = 1024
    println var1

    var1 = "林帅"
    println var1
    println "my name is $var1"

    println test1();

    def var2 = 5
    println var2.class

    var2 = 5.5
    println var2.class

    var2 = 5L
    println var2.class

    var2 = 5D
    println var2.class

    var2 = 'hehe'
    println var2.class

    var2 = false
    println var2.class

    def demoList = [121, 3.14, 'hello', false, null] // 使用[]定义,元素之间用,隔开
    println demoList.size // 获取集合大小
    println demoList[2] // 获取index为2的元素
    // 在结尾添加元素的两种写法
    demoList.add(100)
    demoList << 100
    // 在指定位置添加元素,原本index大于等于3的元素往后退一位
    demoList.add(3, 100)
    demoList.remove(0) // 删除指定index的元素
    demoList -= [3.14, false] // 删除某集合的元素
    // demoList.clear() // 清空集合
    // 使用集合直接调用.each可以对集合进行遍历
    demoList.each {
        println it // it是迭代过程中的每一个元素
    }

    def demoMap = ['name': '林帅', 'age': 18, 'isGay': false]
    println demoMap.size() // 获取map大小
    println demoMap.name // 通过key获取值
    demoMap << ['hehe': '777'] // 添加元素
    demoMap['haha'] = '888' // 添加元素
    // 遍历map
    demoMap.each {
        println it.key
        println it.value
    }

    pick(10, { a, b ->
        if (a % 2 == 0)
            println b * a
    })
    println testMethod(4, 5)

}

def String test1() {
    return "xiaolinzi"
}

def pick(n, closure) {
    for (i in 1..n) {
        closure(i, 2)
    }
}
//可以不写返回类型,不写参数类型,return可以不写,默认取最后一行
def testMethod(a, b) {
    println a + b
    3333
}
1024
林帅
my name is 林帅
xiaolinzi
class java.lang.Integer
class java.math.BigDecimal
class java.lang.Long
class java.lang.Double
class java.lang.String
class java.lang.Boolean
// list
5
hello
hello
100
null
100
100
// map
3
林帅
name
林帅
age
18
isGay
false
hehe
777
haha
888
// end
4
8
12
16
20
9
3333

1、弱类型,不用定义类型,类型之间也可以互相赋值,使用def标识

2、有分号或者没有都可以

3、方法有默认返回最后一行的数据,当最后一行没有时返回空,方法可以缺省返回值类型,默认public

4、在字符串中使用美元符访问变量,单引号和双引号的含义相同,三引号代表多行字符串

5、使用groovyc进行编译

6、Groovy的闭包是一个代码块或者方法指针,代码在某处被定义然后在其后的调用处执行

Groovy语法是在java预发基础上的升级版,有些特性是对java语法的补充提升,多用一下就可以理解了。

Gradle

首先搬官方文档 https://docs.gradle.org/current/userguide/userguide.html ,这个文档写的非常清楚,真的应该好好的读一遍,我只读了前几章,如果以后有机会一定再深入的学习一番。

Gradle的实质是配置脚本,执行一种类型的配置脚本时就会创建一个关联的对象,譬如执行Build script脚本就会创建一个Project对象,这个对象其实就是Gradle的代理对象。

Gradle的三种主要对象解释如下:

  • Project对象:每个build.gradle会转换成一个Project对象。
  • Gradle对象:构建初始化时创建,整个构建执行过程中只有这么一个对象,一般很少去修改这个默认配置脚本。
  • Settings对象:每个settings.gradle会转换成一个Settings对象。

整个构建过程如图所示:

Gradle插件相关知识_第6张图片
Paste_Image.png
settings.gradle

放在工程的根目录,在多工程构建中用于标识对应的多工程module,可以动态的修改module的projectDir等信息。在工程构建的初始阶段为当前项目创建一个Settings类型的实例,创建项目层级结构的Project对象实例。

build.gradle

gradle构建的第二步是执行.gradle目录下的Init script脚本,为接下来的Build script做一些准备工作,一般我们不会修改这个脚本。

接下来第三步就是执行各个工程目录下的build.gradle脚本,将各个task任务及关系进行确认,达成最终的构建目标生成。

gradle构建最重要的就是理解task,其实插件本身就是一个task合集,插件是为了更好的复用和迁移代码,其实和写在build.gradle中是没有任何区别的。

常用的gradle command-line

1、name缩写 gradle aR => gradle assembleRelease

2、gradle -q projects

gradle -q tasks

gradle -q dependencies

前面都可以加上module名

3、-D system property

-P project property

-q Log error only

-i 查看log信息

-d 查看debug信息

https://docs.gradle.org/current/userguide/gradle_command_line.html

task

最后整理一下任务相关,可能整理不完善,后续不断加进来。

1、任务定义

task hello {
    doLast {
        println 'Hello world!'
    }
}
task hello << { // 快捷定义
    println 'Hello world!'
}

2、任务依赖

task intro(dependsOn: hello) {
    doLast {
        println "I'm Gradle"
    }
}

3、动态添加任务目标

hello.doLast {
    println "This is append hello"
}

4、properties声明

ext.pro1 = [ // extra properties
             "test1": "properyTest1",
             "test2": "properyTest2"
]
ext {
    pro2 = "property2"
}
task testProperty { // 任务声明
    ext.myProperty = "myValue"
    doLast {
        println hello.myProperty
        println pro1.test1
        println pro1.test2
        println pro2
        println project.properties.get("test")
        println System.getProperty("test")
    }
}

使用 gradle testProperty -Ptest=test1 -Dtest=test2 试试看吧

5、default task定义

defaultTasks 'hello' 

默认执行hello task

6、理解gradle.taskGraph

gradle.taskGraph.whenReady { taskGraph ->
    println taskGraph.allTasks
}

taskGraph对象包含当前目标任务所包含所有的任务对象

7、project api

project Project The Project instance
name String The name of the project directory.
path String The absolute path of the project.
description String A description for the project.
projectDir File The directory containing the build script.
buildDir File *projectDir*/build
group Object unspecified
version Object unspecified

8、类型任务定义

task('hello') {
    doLast {
        println "hello"
    }
}
task('copy', type: Copy) {
    from(file('srcDir'))
    into(buildDir)
}
tasks.create(name: 'hello') {
    doLast {
        println "hello"
    }
}
tasks.create(name: 'copy', type: Copy) {
    from(file('srcDir'))
    into(buildDir)
}

9、File处理

fileCollection 当前路径下的File Set

fileTree 得到一个所有文件的列表

task testFiles {
    project.files(project.buildDir.listFiles()).each {
        println it.name
    }
    println("**********************")
    FileTree tree = fileTree(project.buildDir)
    tree.include 'outputs/aar/*.aar'
    tree.exclude '*/*/*release*' // 这里必须是路径
    tree.each {
        println it.name
    }
}

10、依赖管理

https://docs.gradle.org/current/userguide/dependency_management.html

中央仓库:

  • mavenCentral,表示依赖是从Central Maven 2 仓库中获取的。
  • jcenter,表示依赖是从Bintary’s JCenter Maven 仓库中获取的。
  • mavenLocal,表示依赖是从本地的Maven仓库中获取的。
  • 自定义maven仓库
  • flatDir 表明系统将在lib目录下搜索依赖
repositories {
    maven {
        url "http://maven.petrikainulainen.net/repo"
        url  uri('/Users/xiaolinzi/testRepo') // 本地仓库
    }
    mavenCentral()
    flatDir {
        dirs 'libA', 'libB'
    }
}

依赖分类:

  • 当项目的源代码被编译时,compile配置项中的依赖是必须的。
  • runtime 配置项中包含的依赖在运行时是必须的。
  • testCompile 配置项中包含的依赖在编译项目的测试代码时是必须的。
  • testRuntime 配置项中包含的依赖在运行测试代码时是必须的。
  • archives 配置项中包含项目生成的文件(如Jar文件)。
  • default 配置项中包含运行时必须的依赖。
  • 在android还会用到provided表示在运行时依赖,编译时取消依赖

声明依赖的方式

dependencies {
    compile group: 'org.springframework', name: 'spring-core', version: '2.5'
    compile 'org.springframework:spring-core:2.5'
    compile('org.hibernate:hibernate:3.0.5') {
        transitive = true // 代表传递依赖被打开,默认打开
    }
    compile module("org.codehaus.groovy:groovy:2.4.7") { // 直接声明传递依赖的版本
        dependency("commons-cli:commons-cli:1.0") {
            transitive = false
        }
        module(group: 'org.apache.ant', name: 'ant', version: '1.9.6') {
            dependencies "org.apache.ant:ant-launcher:1.9.6@jar",
                         "org.apache.ant:ant-junit:1.9.6"
        }
    }
    compile project(':shared') // 依赖一个本地project
    compile fileTree(dir: 'libs', include: '*.jar') // 依赖文件
    compile gradleApi() //
    compile localGroovy()
}

依赖冲突

去除依赖

configurations {
    compile.exclude module: 'commons'
    all*.exclude group: 'org.gradle.test.excludes', module: 'reports'
}

dependencies {
    compile("org.gradle.test.excludes:api:1.0") {
        exclude module: 'shared'
    }
}

文档上还有很多东西没看透彻,以后慢慢补充吧,先写成这样。。>_<

你可能感兴趣的:(Gradle插件相关知识)