Gradle-Android-知识点总结

Android 项目的构建过程是由 Gradle 框架完成的,Gradle 框架是使用 Groovy 语言实现的。以下对 Groovy、Gradle、Android 项目的 Gradle 配置进行总结。

一、Groovy

变量、方法、类、list、map

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// 变量没有固定类型
def name = 'Hello'
// 定义方法
def square(def num) {
num * num
}
// 调用方法
square(2)
// 也可以不用圆括号
square 2
// 类
class MyGroovyClass {
String greeting
}
// 实例化
def instance = new MyGroovyClass()
// 调用方法
instance.setGreeting 'Hello, Groovy!'
println instance.getGreeting()
// list
List list = [1, 2, 3]
list.each() { element ->
println element
}
// map
Map test = [a: 1, b: 2]
println test['a']

闭包

独立代码块,可接受参数,可以有返回值,可以赋值给变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// 1.定义和执行
def myClosure = { println "Hello world" }
myClosure()
// 2.接受参数
// 命名参数
def myClosure = { String str, int num -> print "str, num" }
myClosure("Hello world", 21)
// 一个参数,可用 it
def myClosure = { println it }
myClosure("Hello world")
// 3.闭包引用所在的上下文环境变量:
def myVar = “Hello world”
def myClosure = { println myVar }
myClosure()
// 4.通过 #setDelegate() 切换上下文,从而引用到不同上下文里的变量
def myClosure = { println myVar }
MyClass m = new MyClass()
myClosure.setDelegate(m)
myClosure()
class MyClass {
def myVar = "Hello world"
}
// 5.把闭包当做参数来传递:
myMethod(myClosure)
// 参数只有一个 且 是闭包时,可以省略圆括号
myMethod myClosure
// 用内联的方式传递闭包参数
myMethod { println “Hello world” }
// 接受2个参数
myMethod(21, myClosure)
// 闭包内联
myMethod(21, { println “Hello world” })
// 如果最后一个参数是闭包,可将闭包放在圆括号外
myMethod(21) { println “Hello world” }

文件操作

1
2
3
4
5
6
7
8
9
10
// 输出某个文件
def printFile(def path) {
def file = new File(path)
if (file.exists()) {
file.eachLine { oneLine ->
println oneLine
}
}
}
printFile('anyfile.txt')

二、Gradle

概念:Project、gradle 文件、task、action

每个项目至少有一个 project,每个 build.gradle 文件对应一个 project,每个 project 里包含多个 task,task 里包含多个 action,action 是一个代码块,里面包含了被执行的代码。

从0开始一个 gradle 项目

1
2
// 在一个空目录中
gradle init

会生成 gradle 项目的基本文件,以下是常见 gradle 项目的目录结构:

MyApp

​ |—— settings.gradle

​ |—— build.gradle

​ |—— gradle/

​ |—— gradlew

​ |—— gradlew.bat

gradle 项目的编译执行过程

  1. 初始化:分析有哪些 module 将要被构建,为每个 module 创建对应的 project 实例对象。这个时候settings.gradle文件会被解析,而单个 module 的项目可以不需要这个文件。
  2. 配置阶段:处理所有的模块的 build.gradle 脚本,从顶层 build.gradle 开始,处理依赖,属性等。这个时候每个模块的build.gradle 文件会被解析并配置,这个时候会构建整个 task 的链表(这里的链表仅仅指存在依赖关系的task的集合,不是数据结构的链表)。
  3. 执行阶段:根据task链表来执行某一个特定的task,这个task所依赖的其他task都将会被提前执行。

任务 task

  • task 的定义:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 定义任务
task hello {
// 以下这句顶层任务会在配置阶段被执行
println “Hello world”
}
// 在命令行直接执行 task
$> gradle hello
// 使用 doFirst/doLast
task hello {
doLast {
println “Hello world!”
}
}
// doLast 也可简写为:
task hello << { println “Hello world!” }
  • 带依赖的 task(执行某一个 task,一定会先执行它依赖的 task)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
task taskX(dependsOn: ’taskY’) << { println “taskX” }
task taskY << { println ’taskY’ }
// 或
task taskX << { println “taskX” }
task taskY << { println “taskY” }
taskX.dependsOn taskY
// 或
task taskX << {
dependsOn taskY
println “taskX”
}
task taskY << { println “taskY” }
  • 查看所有 task:
1
gradle tasks

扩展属性

可以在项目级别定义属性,然后在所有模块之间共享这些属性,也可以在模块内部定义和使用属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 定义属性
ext {
prop1 = 1
}
ext.prop2 = 2
// 给 android 模块定义属性
android.ext.prop3 = 3
// 在模块中拿自己模块的扩展属性
println project.ext.prop2
// 在子模块里拿父模块的扩展属性
println rootProject.ext.prop

Gradle Wrapper

因为 gradle 版本会不断更新,每个人本地使用的版本可能会不同,而 gradlew(gradle wrapper)可以算是gradle 的一层包装,使每个人在同一个项目中用相同的版本(在项目里的 gradle/wrapper/gradle-wrapper.properties 文件中)

配置 gradlew 的方法:

1
2
// 在项目中执行
gradle wrapper

会在项目目录中生成:

|—— gradle/ 目录(放一些配置)

|—— gradlew.bat(在 Windows 上用来代替 gradle 命令)

|—— gradlew(在 Linux/Mac 上用来代替 gradle 命令)

三、Android 项目的 Gradle 配置

Android 项目的一般 Gradle 相关结构

  • 顶层 build.gradle

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    // buildscript{} 配置 gradle 本身的库和依赖项(不在这里配置项目的依赖项)
    buildscript {
    // repositories{} 定义 gradle 用来下载依赖的仓库,jCenter 是一个构件仓库,mavenCentral 也是,mavenLocal 则代表本地仓库
    // 相比 mavenCentral,jCenter 下载快(CDN)、上传方便(在 bintray 网站发布)
    repositories {
    jcenter()
    }
    // dependencies{} 配置 gradle 的依赖。以下这个依赖提供了 Android 插件(下面会用到)
    dependencies {
    classpath 'com.android.tools.build:gradle:3.3.0'
    }
    }
    // 配置所有项目都会用到的 repositories 和 dependencies
    allprojects {
    repositories {
    jcenter()
    }
    }
  • 每个项目单独的 build.gradle

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    // 使用某个插件
    // 实际上是调用了 apply() 函数并传入了一个 Map:apply([plugin: 'com.android.application'])
    // Android App 的主项目必须使用这个插件,提供了 android{} 代码块功能
    // 其他子项目使用 'com.android.library'
    apply plugin: 'com.android.application'
    // 所有关于 android 的 build 配置
    android {
    compileSdkVersion 28
    buildToolsVersion "28.0.3"
    defaultConfig {
    applicationId 'com.example.myapp'
    minSdkVersion 15
    targetSdkVersion 28
    versionCode 1
    versionName "1.0"
    }
    // 构建类型,根据不同 buildType 可在执行不同构建类型时用不同的配置、做不同的变量替换
    buildTypes {
    debug {
    minifyEnabled false
    buildConfigField "String", "API_URL", "http://test.example.com/api"
    resValue "string", "app_name", "Example Debug"
    }
    release {
    minifyEnabled true
    signingConfig signingConfigs.release
    buildConfigField "String", "API_URL", "http://test.example.com"
    resValue "string", "app_name", "Example"
    }
    }
    }
    // 本模块的依赖
    dependencies {
    implementation project(":submodule")
    implementation "androidx.appcompat:appcompat:1.1.0"
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    }
  • 属性文件(.properties)

    • gradle.properties 文件:配置项目的 gradle 属性
    • local.properties 文件:配置本地环境属性,如 SDK 安装路径(该文件由 Android Studio 自动生成)

Android Gradle 的常用 task

  • assemble: 对所有的 buildType 生成 apk 包(该 task 依赖 assembleDebug 和 assembleRelease,所以如果只需要debug 或 release,可只执行其中一个)。

  • clean: 移除所有的编译输出文件,例如 apk 包、build/ 目录。

  • check: 执行 lint 检测编译。

  • build: 同时执行 assemble 和 check 命令。

四、参考

关于 Groovy 更多参考:http://docs.groovy-lang.org/latest/html/documentation/

关于 Gradle 的更多参考:https://docs.gradle.org/current/userguide/userguide.html

关于 Android Gradle 构建的更多参考:https://developer.android.com/studio/build/