Gradle基础

作者: 花京院典明 | 来源:发表于2017-05-05 17:11 被阅读261次

Gradle是基与Groovy的脚本配置的构筑工具,用与构筑Java及Android应用.

Gradle

Gradle是个构筑工具,本身是一个框架,提供了一系列的API,使用中则是执行.Gradle脚本文件,借助与其中的配置来进行构筑.
简单的来说,.Gradle文件就是使用Groovy语言配置及调用Gradle的API的脚本

对与Gradle而言,一个Project是一个执行单元,一个Project对应了一个build.gradle脚本.一个App或一个Library都算是一个Project.

GradleWrapper

一个使用Gradle的项目,如果在没有安装Gradle或对应的版本不对的环境时,需要手动去配置环境.为了避免这个情况,在项目中自带了Gradle的运行环境配置.
就是gradle\wrapper目录.其配置文件为gradle-wrapper.properties.

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip

项目中gradlewgradlew.bat就是不同平台下的gradle命令行.他使用的是指定的gradle环境.
1 首先会在指定的路径下wrapper/dists下查找是否有对应版本的环境
2 如果没有则会根据gradle-wrapper.properties中的distributionUrl下载对应的版本.

路径优先级如下

  • GRADLE_USER_HOME
  • GRADLE_HOME
  • 如果使用AndroidStudio会在OffLine Work指定的目录
  • User/.gradle

如上面的distributionUrl,实际上就是下载gradle-3.3-all.zip到指定路径的wrapper/dists/gradle-3.3-all/乱码/目录下.如C:\Users\花京院\.gradle\wrapper\dists\gradle-3.3-all\55gk2rcmfc6p2dg9u9ohc3hw9
这个乱码目录自动生成的.下载时会生成.lck文件.下载完成时会生成.ok文件.
所以,如果不能翻墙或下载很慢时,可以停止下载,从下载速度好的镜象网址中下载对应的版本放在该目录下,并新建一个空txt文件,改名成.ok文件.如gradle-3.3-all.zip.ok

为了更好的使用Gradle,可以注意两点

  • 配置GRADLE_USER_HOME路径
  • gradle-wrapper.properties中的distributionUrl地址改成镜象的地址.
    https\://services.gradle.org/distributions/gradle-3.3-all.zip改为http\://mirrors.flysnow.org/gradle/gradle-3.3-all.zip

一个不错的镜象网址

Project

Project是一个接口,是Gradle的核心.通过Project来访问所有的Gradle的功能.Projectbuild.gradle是一一对应的关系.
一个项目必须有一个builde.gradle.它对应的Project叫做rootProjcet.这个Project对其它Project提供基础性及公共性的配置.它会创建一个Settings的实例并根据setting.gradle来配置这个实例.

  • Project里含有一个容器TaskContainer接口.用与创建,存取及管理所有的Task.
  • Project里含有一个容器ConfigurationContainer接口,来管理对应的项目配置
  • Project里含有一个DependencyHandler接口用与管理项目的依赖
  • Project里含有一个RepositoryHandler接口用来注册和管理依赖所需的Repository.

属性property

Project可以声明很多属性,没有类型限制.有多种来源

  1. Project自身带的属性
  2. 额外属性(extra properties),每个Project都持有一个Map用来存放额外属性.这个Map的声明为ext.所以可用ext.属性名来访问或用ext.属性名=xxx来赋值
  3. 通过插件添加到extensionsextension,可以做为同名的只读属性
  4. 通过插件添加convention属性,插件可以通过Projectconvention对象添加属性和方法
  5. Project的属性

Project的动态方法

Project中的方法有多个来源.

  1. Project自身的方法
  2. builde.gradle中声明的方法
  3. 通过插件提供的额外方法
  4. 把Task当成方法,通过把Task名当成方法名来调用Task中的Action或闭包.
  5. Project的方法,顶层直到rootProject
  6. 闭包形式的属性(property).可以把属性当成方法调用.

TASK

task在gradle里可以看成是一个执行任务.除了自定义的task,其它的task都是通过pluging引入的.像编译,打包,安装这些都是定义好的task.

windows调用task的方法是gradle或gradlew task名 ,在linux或mac下是./gradle或gradlew task名

task在Gradle中是个接口,其默认实现类为DefaultTask.其它的实现类都是继承与此.

创建Task

可以通过TaskContainer对象的create方法来创建Task.但通常是使用task关键字来创建Task

使用task关键字创建task实际上是使用了Project对象的task方法来创建的.共有四个重载方法.调用此方法会创建task并保存在其中的TaskContainer里.方法如下

Task task(String name)
Task task(String name, Closure configureClosure) //Cloure就是闭包
Task task(Map<String,?> args,String name)
Task task(Map<String,?> args,String name,Closure configureClosure)
//例子
task hello
task hello {xxx} //groovy语法
task hello(type:jar)
task hello(type:jar) {xxx}   //gradle的DSL

doFirst和doLast

task执行任务是基与Action接口的.基内部维护了一个List,通过List<Action<? super Task>> getActions()方法可获取这个容器.在执行Task时就是遍历这个容器,调用每个Action

Task添加Action的方法就是doFirstdoLast.添加至List的头和尾.这说明该List是LinkedList

参数有两种,一种为Action<? extend Task>,另一种为闭包.通常使用闭包这种简便的方式

在gradle提供的DSL中对doLast提供了一个简化写法

task hello <<{
  xxx
}
//等同与
task hello {
  doLast {
    xxx
  }
}

读懂Gradle脚本

如上说的,Gradle脚本是基与Gradle的API.所以脚本中基本上都是在调用Gradle的API.
因为脚本使用的是Groovy语言,那么明白Groovy对了解脚本有很大的帮助.这里只说几个要点

  • Groovy是基与Java的.可以看成是Java言的简写形式.也就是说可以把Groovy完全替换成Java代码.
  • 在Groovy中所有的都是对象,基本数据类型对应的是其对象类,容器使用的是ListMap,容器的声明是[],每个元素以,分隔.
  • 在groovy中Map的定义是[key:value],key必须是字符串,如果不用''""包含则会自动转成对应的字符串,如果key想使用变量引用,则需要加上(),当方法参数时如果只有一个键值对时可以省略[ ]
def map=[k:`v`]
//这里key是"k",value是"v"
def key="k"
def map=[key:'value']
//这里key是"key"而不是k
def map=[(key):"value"]
//这里的key是'k'
  • Groovy中不需要声明类型,但是所有的参数都是有类型的.其顶层是Object.声明一个变量或方法都用def关键字
  • Groovy中有闭包,闭包是被{}包裹的可执行代码.可以看成是一个Runable,不过可以传递参数,如果不设置参数,则有一个默认的参数,在闭包中用it表示.类型会自动推导
  • Groovy里方法调用是可以链式调用的.方法名+空格+参数表示一个方法调用.省略了括号,在链式调用中方法名+()表示调用空参的方法.如果链式调用为奇数,最后一个参数视为成员变量,如
    from a into b
    from(a).into(b);
    
    from a,b init() name
    from(a,b).init().name;
    
    from {} into {} name
    from({}).into({}).getName();
    
  • Groovy里顶层方法调用可以省略括号,参数间以,分隔.但参数是方法调用的话是不能省略括号的.
    from(a)//可以写成from a
    from(a,get(b)) //不能写成 from a,get b,必须写成from a,get(b)
    
  • 方法参数中含有闭包的可以把闭包放到括号外,并省略括号及,
    from(a,{})
    from a {}
    

闭包

闭包是一个被{}包含的可执行代码.在Java中是没有闭包存在的,因为Groovy最终会转化为Java代码.实际上闭包会被转化成对应的对象.原理类似与Java8的Lamda.

比如说在对容器进行遍历时调用foreach方法.就可以传入一个闭包对容器的元素进行操作.这个闭包是没有传递参数的.在闭包中这个元素可以用it来调用.可以理解为创建了一个Runable,含有一个成员变量it.这个变量就是遍历时对应的元素

调用Gradle的方法,传入一个闭包.可以简单的理解为需要传入一个指定的继承Runable的对象或者说是匿名内部类,它的run()方法由自己来实现.这在Gradle里叫委托.

在Gradle里需要传入闭包的方法都是委托指定的对象.所以在闭包中可以直接调用该对象的方法.具体的闭包对应的对象及其可调用的方法就需要查看Gradle的API文档.

解析几个常见的脚本


apply plugin: 'com.android.library'
apply from: 'config.gradle'

实际上都是在调用Gradle的API,apply(Map map)方法,在方法调用时可以通过空格来省略方法的括号.实际可以写成
apply([plugin:'com.android.library'])

上面的代码也可以合起来写
apply [plugin: 'com.android.library',from:'config.gradle']


android {
    compileSdkVersion 24
    buildToolsVersion '24.0.1'

    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 24
        versionCode 1
        versionName '1.0'

    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}
  1. 这里首先调用了android方法,参数是个闭包A.这里是创建了一个Android对象.闭包内的内容为对其的配置
  2. A中调用compileSdkVersion,buildToolsVersion,defaultConfigbuildTypes方法.前两个方法为Android对象的方法,后两个方法的参数为闭包B和C
  3. B中调用了四个方法,C中调用了闭包D,在D中调用了release方法,参数为闭包E
  4. E中调用了minifyEnabledproguardFiles方法
  5. proguardFiles方法的参数为proguard-rules.pro字符串及方法getDefaultProguardFile('progurad-android.txt')方法的返回值

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    compile 'com.android.support:support-v4:19.1.0'
}
  1. 这里调用了dependencies方法,闭包中为其配置
  2. compile为添加依赖的方法.
  3. fileTree(include: ['*.jar'], dir: 'libs')做为compile方法的参数.fileTree是个方法,参数为一个List用来表示添加的类型和一个Map用来表示文件路径,
  4. 'com.android.support:support-v4:19.1.0'为依赖的名称.构建时会通过RepositoryHandler在注册的Repository里查找.

task clean(type: Delete) {
    delete rootProject.buildDir
}
  1. 声明了一个cleantask.
  2. task的类型为Delete,所以在闭包中可以使用对应的方法delete
  3. 删除的路径为rootProject.buildDir变量保存的路径

相关文章

网友评论

    本文标题:Gradle基础

    本文链接:https://www.haomeiwen.com/subject/wrdstxtx.html