从编程的角度理解gradle脚本??Android Studio脚本构建和编程
随着Android 开发环境从Eclipse转向Android Studio,我们每个人都开始或多或少要接触gradle脚本,大多数人将gradle看做构建工具,出现问题不知如何着手分析,只能寄希望百度能找到解决方案,其实大可不必。
如果我们把gradle看做编程框架,并理清gradle脚本与gradle对象的关系,通过查阅文档,不但能清晰理解gradle脚本,而且出现问题再也不用百度,通过查阅文档就能轻松解决问题。
本文就通过一个最普通的gradle工程,告诉大家如何通过查阅api文档来看懂Android里面的gradle 脚本。
一、gradle介绍
gradle基于的语言是groovy,而groovy语言是基于java语言的一个扩展,它完全兼容java语言的类库,所以在gralde脚本中你完全可以使用你熟悉的java语言来编程。在本文最后我们会给出一个直接在gradle脚本中使用java编程的例子。
由于本文仅仅是让大家能看懂脚本,而不是自己去编写,所以groovy和gradle的细节不是本文的重点,有需要的同学自行百度。这里要提的一点是groovy语言的函数调用是虽然和java类似,但是它是可以省略括号的,特别是当它的最后一个参数是闭包的时候。
println(“aaa” )//这个是可以的,
println“aaa” //这个也没有问题。
是不是发现了一个秘密:我们在gradle脚本里全是各种函数调用!!
Gradle api文档路径:https://docs.gradle.org/current/dsl/
由于我们也用到了Android 插件,所以我们也需要插件的文档,这个文档比较特殊,它是一个git工程,在线浏览老是显示html的源码而非页面,所以我建议大家将它clone回本地,然后用浏览器打开,工程地址:https://github.com/google/android-gradle-dsl.git
二、gradle脚本和gradle 类对应关系
稍稍浏览下gradle的文档,我们会发现工程里面的gradle脚本,其实和gradle的对象是对应的:
1.Gradle:全局对象,一次gradle构建对应一个Gradle对象;
2.Project:每个工程都是一个Project对象,它对应一个build.gradle文件;
3.Settings:对应一个Setting.gradle文件;
4.Task:代表要执行的工作,一个Project会有一个或多个Task用于完成构建的工作,Project会通过合理设置Task之间的依赖来组织构建流程,完成最终的构建任务。
三、脚本执行流程与对象生成
1.每次调用gradle 执行时,会先生成一个Gradle对象,里面保存一些全局的信息;
2.然后会解析setting.gradle,生成Settings对象,一般在setting.gradle中主要是调用include方法,导入工程下的各个子模块;
3.接下来会执行导入的各个子工程的build.gradle,生成并配置Project对象;
一般在build.gradle中,会调用Project的apply方法,引入插件,在插件中完成定义各种属性以及创建所需的Task。
四、实例解析
我们以一个Android studio 默认app样例工程结构为例,工程包含的gradle脚本目录结构:
1. setting.gradle
setting.gradle只有一行语句:
include ':app'
这里的include其实是Setting的一个函数,‘:app' 是函数调用的参数。
那我们在setting.gradle里面还能写什么呢?因为setting.gradle对应的是gradle中的Settings对象,那查下Settings的文档(https://docs.gradle.org/current/dsl/org.gradle.api.initialization.Settings.html),看下它都有哪些方法,哪些属性,就知道在setting.gradle能写什么了:
比如:
include ':Common'
project(':Common').projectDir = new File(settingsDir,'../../SDK/Common/')//include 调用后,生成了一个名为:Common的Project对象,project(':Common')取出这个对象,设置Project的 projectDir属性。
那projectDir哪里来的?请看Project类的文档。
2. build.gradle
接下来我们来看build.gradle,build.gradle对应一个Project对象,而Project本身是一个Build script:
而BuildScript可以包含哪些东西呢?
是不是看到了很多老朋友?buildscript , dependencies 。。
看了这里我们应该就能明白在build.gradle里面可以写哪些东西了。
这里要说明的一个重要的点是buildscript,任何一个build.gradle执行的时候,会优先处理buildscript,它是来给脚本建立运行环境的,什么是运行环境?
一般而言就是下载所需要的插件,举个例子,android工程都需要android插件,它们都是通过下面的方式引入的:
buildscript {
repositories {//告诉如果本地没有缓存,去哪个远程仓库下载插件
mavenCentral()
}
dependencies {
//这就是我们在applyplugin:com.android.application时的插件jar
classpath 'com.android.tools.build:gradle:1.3.0'
// NOTE: Do not place your application dependencies here; theybelong
//in the individual module build.gradle files
}
}
repositories {//告诉如果本地没有缓存,去哪个远程仓库下载编译时依赖的库
mavenCentral()
}
上面的repositories, dependencies都是函数调用哦~~
看到上面的两个一模一样的repositories 了吗?他们的作用是不一样的,在buildscript里面的那个是插件初始化环境用的,用于设定插件的下载仓库,而外面的这个是设定工程依赖的一些远程library的下载仓库的。
在build.gradle中引入插件,是我们常见的动作:
apply plugin: 'com.android.application'
查阅Project的文档(https://docs.gradle.org/current/dsl/org.gradle.api.Project.html).apply是Project的一个方法,
3. android相关部分
查阅android插件的文档:(file:///home/test/android-gradle-dsl/1.5/index.html)
上面就是我们在android{}里面能写的所有block的信息,然后在每个block里面能写什么继续点击进去察看有哪些属性和方法就可以了,
比如signingConfigs:
signingConfigs{
release {
storeFile file('../sign/release.jks')
storePassword "[email protected]!d"
keyAlias "small"
keyPassword"[email protected]!d"
}
}
本文至此可以告一段落,相信大家结合文档应该能弄明白gradle脚本里面的每个代码块的意义了。
五、Android工程间的父子关系
需要补充的是:上面例子工程的结构中,工程之间是存在父子关系的,比如RxJava-Android-Samples/build.gradle对应的Project是RxJava-Android-Samples/app/build.gradle对应的Project的父亲,而在父Project中做的操作是会被子Project继承的,比如如果在 父Project引入过了android 插件,则在子Project中可直接引用,不需要重写一个buildscript块。
1.RxJava-Android-Samples/build.gradle
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.3.0'
// NOTE: Do not place your application dependencies here; theybelong
//in the individual module