Gradle入门及相关总结

Gradle是一款非常优秀的构建系统工具,它的DSL是基于Groovy实现。可以方便通过代码控制这些DSL达到构建目的,Gradle构建大部分功能是通过插件方式来实现。

1.Gradle入门及Gradle Wrapper:

Wrappe是对Gradle的一层包装,便于团队在开发过程中统一Gradle构建版本,避免因为Gradle构建版本不同意带来的不必要麻烦。

  •  gradlew和gradlew.bat分别是Linux和window下的可执行脚本,用法跟Gradle原生命令一样;
  • gradle-wrapper.jar是具体业务逻辑实现的jar包,gradlew最终还是使用Java执行这个jar包来执行相关Gradle操作;
  • gradle-wrapper.properties是配置文件,用于配置使用哪个版本的Gradle等。
distributionBase=GRADLE_USER_HOME     //下载Gradle压缩包解压后存储的主目录
distributionPath=wrapper/dists        //相对于distributionBase解压后Gradle压缩包路径
zipStoreBase=GRADLE_USER_HOME        //同distributionBase,只不过存放zip压缩包
zipStorePath=wrapper/dists           //同distributionPath,只不过存放zip压缩包
//Gradle发行版压缩包的下载地址
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip

gradle-wrapper.properties是由Wrapper Task生成的,可以自定义配置Wrapper Task来达到配置gradle-wrapper.properties。在build.gradle构建文件中录入脚本:

task Wrapper(type: Wrapper){
    gradleVersion = '5.4.2'
    distributionBase='GRADLE_USER_HOME'
    distributionPath= 'wrapper/dists'
    zipStoreBase= 'GRADLE_USER_HOME'
    zipStorePath= 'wrapper/dists'
    distributionUrl= 'https://services.gradle.org/distributions/gradle-5.4.1-all.zip'
}
  • 也可以在Gradle脚本中加入日志信息:logger.info()等日志级别信息用于调试。

 

2.Groovy基础:

Groovy是基于JVM虚拟机的一种动态语言,它的语法与Java非常相似,由Java入门Groovy基本没有任何障碍。Groovy完全兼容Java,又在此基础上增加了很多动态类型和灵活特性,比如闭包,支持DSL,是一门非常灵活的动态脚本语言。

  • 字符串:单引号和双引号都可以定义字符串,其中单引号标记是纯粹的字符串常量,而双引号是可以表示表达式中进行运算;
task printStringClass << {
    def str1 = '单引号字符串'
    def str2 = "双引号字符串"

}
  • 集合:与Java中的相比更加简洁
task printList << {
    def numList = [1,2,3,4]
    println numList.getClass().getName()
    println numList[2] //访问第三个元素
    println numList[-1] //访问最后一个元素
    numList.each {
        println it      //遍历访问

    }
}

task printMap << {
    def map1 = ['width':1920,'height':1080]
    println map1.getClass().getName()
    println map1['width']
    map1.each {
        println("key:${it.key},value:${it.value}")
    }
}
  • 方法:Groovy的调用方法时()可以省略,return可以省略当没有return时就会用最后一句代码作为返回值,代码块可以作为参数传递;
task invokeMethod << {
    method1 1,2
    method2(3,4)
}

def method1(int a,int b) {
    println(a+b)
}

def method2(int a,int b) {
    if (a > b) {
        a
    }else {
        b
    }
}
  • JavaBean:在Java中访问和修改JavaBean的属性,要重复生成getter/setter方法。而Groovy不用;
  • 闭包概念:是一段代码块;
task helloClosure << {
    //使用自定义的闭包
    customEeach {
        print it
    }
}

def customEeach(closure) {
    for (int i = 0; i < 10; i++) {
        closure(i)
    }
}
  • 向闭包传递参数:当参数为多个时需要一一列举出来;
task helloClosure << {
    //使用自定义的闭包
    eachMap {
        // -> 用于把参数和主体区分开来
        k,v ->
            println("${k} is ${v}")
    }
}

def eachMap(closure) {
    def map1 = ["name":"王麻子","age":"18"]
    map1.each {
        closure(it.key,it.value)
    }
}
  • 闭包委托:Groovy的闭包有thisObject/owner/delegate三个属性,当在闭包内调用方法时,由它们来确定使用哪个对象来处理。默认delegate和owner时相等的,但delegate是可以被修改的;
task helloClosure << {
    new Delegate().test {
        println("thisObject:${thisObject.getClass()}")
    }
}

class Delegate {
    def test(Closure<Delegate> closure){
        closure(this)
    }
}
  • DSL(Domain Specific Language):领域特定语言,专门专注特定领域的语言,它在于专,而不是全。Java是一种通用全面语言。

 

3.Gradle构建脚本基础:

  • Settings文件:用于初始化以及工程树的配置,设置文件默认文件名为setting.gradle,放在根目录的工程下;

设置的大多的作用都是为了配置子工程,在Gradle中多个工程是通过工程树表示的。相当于Android Studio看到Project和Module概念一样。根目录相当于Android Studio的Project,一个根目录可以有很多子工程,也就是有很多Module。

  • Build文件:每个Project都会有一个Build文件,该文件是该Project构建入口,可以在这里针对该Project进行配置,如配置版本/依赖库/添加入插件等;可在主Build文件设置所有子模块的配置信息。
subprojects {
    apply plugin:'java'
    repositories{
        jcenter()
    }
}
  • Project以及Tasks:

在Gradle中可以有很多Project,可以定义创建一个Project用于生成jar/也可以定义另外一个Project生成war包等;一个Project就是在业务范围内,被抽象出来的一个个独立模块可以根据项目情况抽象归类,最后一个个Project组成整个Gradle;

一个Project中又包含很多Tasks,Tasks就是一个操作,一个原子性的操作。

  • 创建Tasks:Tasks是Project对象的一个函数。原型为 create(String name,Closure configureClosure),第二个参数是一个闭包;
task helloClosure{
    
}
  • 任务依赖:任务之间是可以有依赖关系的,可以控制任务先于哪个任务执行或后于哪个任务执行;在任务创建的时候,可以通过dependsOn指定其依赖的任务;
task helloClosure <<{
    new Delegate().test {
        println("thisObject:${thisObject.getClass()}")
    }
}

task sayHello(dependsOn:helloClosure){

}
  • 任务间通过API控制/交互:

创建一个任务和定义一个变量是一样的,变量名就是定义的任务名,可以使用任务名通过Tasks中API访问方法/属性/或对任务重新配置。

  • 自定义属性:Project和Tasks都允许添加自定义属性,要添加自定义属性通过对应的ext属性即可实现;相比于局部变量自定义属性作用域是整个Project;
//自定义一个project的属性
ext age = 18
//自定义一个project的代码块属性
ext {
    name = '王麻子'
    age = 18
}

 

4.Gradle任务:

  • 多种方式创建任务:

第一种直接以任务名创建任务的方式:

def Task taskOne = task(taskOne)

第二种以任务名字+一个该任务配置的Map对象来创建任务:

def Task taskTwo = task(taskTwo,group: BasePlugin.BUILD_GROUP)

Task参数中Map的可配置项:

配置项 描述 默认值
type 基于存在的Task来创建,和继承类似 DefultTask
overwrite 是否替换存在的Task,和type配合用 false
dependOn 用于配置任务的依赖 []
action 添加到任务的一个action或闭包 null
decription 用配置任务的描述 null
group 用于配置任务的分组 null

第三种方式以任务名字+闭包配置的方式:

  • 多种方式访问任务:

第一种直接通过任务名称访问和操作该任务;

第二种通过访问集合的方式访问创建的任务;

task["taskOne"].properties{
    
}

第三种通过名称访问,有get和find两种方式:

tasks.findByName("taskOne")
  • 任务的分组和描述:
def Task taskOne = task(taskOne)
taskOne.group = BasePlugin.BUILD_GROUP
taskOne.description = "任务的描述"
  • << 操作符号:在Gradle的Task是doLast()方法的短标记形式;
  • 任务的执行分析:当执行任务时,其实就是执行其拥有的actions列表,这个列表保存在Task对象实例中的action成员变量中,类型为List,一个任务执行方法有doFrist/doSelf/doLast;
  • 任务的排序:通过任务的shouldRunAfter和mustRunAfter两个方法控制一个任务应该或者必须在另一个任务之后执行;
  • 任务的启动和禁用:通过enable属性来设置启动和禁用,默认为true;
  • 任务的onlyIf的断言:是一个表达式,有onlyIf方法接受一个闭包作为参数,如该闭包返回为true该任务执行否则跳过;

 

5.Gradle插件:

  • 插件作用:插件会扩展项目的功能,在项目的构建过程中做很多事

可以添加任务到项目中,帮忙完成一些事,如测试/编译/打包等;

可以添加依赖配置到项目中,如依赖的第三方库;

可以向项目中现有的对象类型添加新的扩展属性/方法等,有助于配置/优化构建;

可以对项目进行一些约定。

  • 应用插件:

应用二进制插件,二进制插件就是实现了org.gradle.api.Plugin的插件:

apply plugin: 'org.gradle.api.plugins.JavaPlugin'
  • 应用脚本插件:
apply form: 'version.gradle'
  • apply方法的其他用法:
void apply(Closure closure);
void apply(Action<? super ObjectConfigurationAction> action);
void apply(Map<String, ?> options);

apply {
    plugin 'java'
}
  • 应用第三方发布的插件,buildscript{}是在构建项目之前,为项目进行前期准备和初始化相关配置依赖地方,配置好所需的依赖就可以应用插件了:
buildscript {
    repositories {
        google()
        jcenter()       //构建脚本引入jcenter
        
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.5.2'
        
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}
  • 使用plugin DSL应用插件;
  • 自定义插件:自定义插件必须实现Plugin接口,这个接口只有一个apply方法,该方法在插件被应用时被执行。
class mySelfPlugin implements Plugin<Project> {

    @Override
    void apply(Project target) {

    }
}

 

6.Java Gradle插件:

  • Java插件的运用:
apply plugin:'java'

通过以上脚本的应用之后,Java插件会为工程添加很多有用的默认设置和约定,如源代码的位置/单元测试代码的位置/资源文件的位置等。一般情况下最好遵循它的默认设置。

  • Java插件约定的项目结构:

默认情况下,Java插件约定src/main/java为我们项目源代码存放目录;src/main/resources为要打包的文件存放目录如一些Properties配置文件和图片等;src/test/java为我们单元测试存放目录;src/test/resources为存放单元测试中使用的文件。

也可以新建一个源集,目录用于存放其他结构的代码资源,如下:

sourceSets {
    vip{
        
    }
}
  • 配置第三方依赖:
  repositories {
        //配置仓库
        mavenCentral()
        maven {
            url'http://www.mavenurl.com/'
        }
        
    }
    //配置依赖
  dependencies {
        compile 'com.squareup.okhttp3:okhttp:3.0.1'
       
    }

Gradle提供的配置依赖:

名称 继承于 被哪个任务使用 意义
compile _ compileJava 编译时依赖
runtime compile _ 运行时依赖
testCompile compile compileTestJava 编译测试用例时依赖
testRuntime runtime testCompile test 仅在测试用例运行时依赖
archive —— uploadArchive 该项目发布构建(jar包等)依赖
default runtime _ 默认依赖配置

Java插件可以为不同源集在编译时和运行时指定不同的依赖。

dependencies {
        mainCompile 'com.squareup.okhttp3:okhttp:3.0.1'
        VIPCompile 'com.squareup.okhttp3:okhttp:2.5.1'
    }

依赖通用使用格式:

名称 继承于 被哪个任务使用 意义
sourceSetCompile _ sourceSetCompileJava 为指定源集提供编译时依赖
sourceSetRuntime sourceSetCompile _ 为指定源集提供运行时依赖

项目依赖:

dependencies {
        compile project('项目名称')    //项目名在同一目录下
        compile files('lib/项目名称')   //项目名在同一下lib目录下
        compile fileTree(dir:'libs',include:'*.jar')    //包含所有libs,后缀为.jar文件
    }
  • 源码集合(sourceSet)概念:是Java插件用来描述和管理代码及资源的一个抽象概念,是一个Java源代码文件和资源文件的集合。通过源集,可以方便地访问源代码目录,设置源集属性,更改源集的Java目录或者资源目录等;有了源集可以针对不同的业务和应用对源代码进行分组。

Java插件在Project下为我们提供了一个sourceSet属性以及一个sourceSet{}闭包来访问和配置源集。

常用源集属性:

属性名 类型 描述
name String 它是只读的,如main
output.classesDir File 该源集编译后的class文件目录
output.resourcesDir File 编译后生成的资源目录
compileClasspath FileCollection 编译该源集时所需的classpath
java SourceDirectorySet 该源集的Java源文件
java.srcDir Set 该源集Java源文件所在目录
resources SourceDirectorySet 该源集的资源文件
resources.srcDir Set 该源集的资源文件所在目录

 

  • Java插件添加的任务:

Java插件添加的通用任务:

任务名称 类型 描述
compileJava JavaCompile 使用javac编译Java源文件
processResources Copy 把资源文件拷贝到生产的资源目录里
classes Task 组装生产的类和资源文件目录
compileTestJava JavaCompile 使用javac测试Java源文件
processTestResources Copy 把测试资源文件拷贝到生产的资源目录里
testClasses Task 组装生产的测试类和相关资源文件目录
jar Jar 组装Jar文件
test Test 使用JUnit或TestNG运行单元测试
uploadArchives Upload 上传包含jar的构建,使用archive{}闭包配置
clean Delete 清除构建生成的目录文件
cleanTaskName Delete 删除指定任务生成的文件,
javacdoc Jar 使用javacdoc生成Java API文档

源集任务:

任务名称 类型 描述
compileSourcesJava JavaCompile 使用javac编译指定源集的Java源代码
processSourcesSetResources Copy 把指定源集的资源文件复制到生产文件下的资源目录中
sourceSetClasses Task 组装给定源集的类和资源文件目录
  • Java插件添加的属性:

Java插件添加了很多常用的属性,这些属性都被添加到Project中,可以直接使用;

Java插件添加属性的源集属性:

属性名 类型 描述
sourcesSet SourcesSetContainer 该Java项目的源集,可以访问和配置源集
sourcesCompatibility JavaVersion 编译Java源文件使用的Java版本
targetCompatibility JavaVersion 编译生成的类的Java版本
archiveBaseName String 打包jar或zip文件的名称
manifest Manifest 用于访问或配置的manifest清单文件
libDir File 存放生成的类库目录
distsDir File 存放生成的发布的文件的目录
  • 多项目构建:

多项目构建,其实就是多个Gradle项目一起构建,一起通过Settings.gradle配置管理。每个项目下都有一个build文件对该项目进行配置,然后采用项目依赖就可以实现多个项目协作。

  • 发布构件:Gradle构建的产物,称之为构件;一个构件就是一个jar,也可以是一个zip包或war包;发布构件是通过artifacts{}闭包配置的;uploadArchives是一个Upload Task,用上传发布构件。
apply plugin: 'java'

task publishJar(type: Jar)

artifacts {
    archives publishJar
}

uploadArchives{
    repositories{
        flatDir{
            name 'libs'
            dir '$projectDir/libs'
        }
        mavenCentral()
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章