使用Kotlin语言编写Andriod Gradle脚本

概述

当我们通过AS新建一个新的项目的时候,工程的结构目录如下图所示

其中,以gradle结尾的文件(图中红框圈出),是我们在Android开发中经常需要修改的gradle脚本文件。通常gradle脚本是由Groovy语言编写的,例如:

这种写法称为DSL,指的是用于一个特定领域的语言。Groovy本身不是DSL语言,它是一种通用语言,但是因为Groovy的语言的特性对DSL提供了很好的支持,Kotlin语言也是如此。Groovy以及Kotlin语言有一个这样的特性:如果一个函数的最后的一个参数是一个lamda表达式,则可以写在()之外,如果这个函数只有一个参数并且就是lamda表达式,那么()也可以省略。因此,以上图中显示的脚本的{}就可以理解为一个函数。

根目录下的 build.gradle => build.gradle.kts

Kotlin编写gradle脚本需要将脚本文件的后缀添加kts(kotlin-script)。

  • build.gradle

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    buildscript {
    repositories {
    google()
    jcenter()
    }
    dependencies {
    classpath 'com.android.tools.build:gradle:3.2.1'
    // NOTE: Do not place your application dependencies here; they belong
    // in the individual module build.gradle files
    }
    }

    allprojects {
    repositories {
    google()
    jcenter()
    }
    }

    task clean(type: Delete) {
    delete rootProject.buildDir
    }
  • build.gradle.kts

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    buildscript {
    repositories {
    google()
    jcenter()
    }
    dependencies {
    classpath("com.android.tools.build:gradle:3.2.0")
    // NOTE: Do not place your application dependencies here; they belong
    // in the individual module build.gradle files
    }
    }

    allprojects {
    repositories {
    google()
    jcenter()
    }
    }

settings.gradle => settings.gradle.kts

既然根目录的gradle脚本修改了名字,那么就要告知gradle编译工具寻找修改名字之后的文件,因此要在settings.gradle.kts文件中指定。

  • setting.gradle
    1
    include ':app'

-setting.gradle.kts

1
2
include("app")
rootProject.buildFileName = "build.gradle.kts"

Module中的 builde.gradle => build.gradle.kts

- build.grale

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
apply plugin: 'com.android.application'

android {
compileSdkVersion 28
defaultConfig {
applicationId "me.jiuahuan.gradle"
minSdkVersion 18
targetSdkVersion 28
versionCode 1
versionName "1.0.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

dependencies {
implementation 'com.android.support:appcompat-v7:28.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

  • build.gradle.kts
    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
    plugins {
    id("com.android.application")
    }

    android {
    compileSdkVersion(28)
    defaultConfig {
    applicationId = "me.jiahuan.gradle"
    minSdkVersion(18)
    targetSdkVersion(28)
    versionCode = 1
    versionName = "1.0.0"

    testInstrumentationRunner = "android.support.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
    getByName("release") {
    isMinifyEnabled = false
    proguardFiles("proguard-rules.pro")
    }
    }
    }

    dependencies {
    implementation("com.android.support:appcompat-v7:28.0.0")
    testImplementation("junit:junit:4.12")
    androidTestImplementation("com.android.support.test:runner:1.0.2")
    androidTestImplementation("com.android.support.test.espresso:espresso-core:3.0.2")
    }

统一第三方依赖版本管理

通常在开发过程我们会统一规划第三方依赖库的版本或者统一编译版本,我们会在根目录的build.gradle中编写,如:

1
2
3
4
5
6
7
8
9
10
ext {
config = [
compileSdkVersion: 27,
minSdkVersion : 19,
targetSdkVersion : 27,
versionCode : 1,
versionName : "0.1.0",
supportVersion : "27.1.1" // support依赖库的版本
]
}

然后在module的build.gradle中可以这样编写

1
2
implementation 'com.android.support:appcompat-v7:' + config.supportVersion
implementation 'com.android.support:design:' + config.supportVersion

但是在Koltin写法中并不是这样的,官方推荐的是新建一个叫buildSrcModule(这个也是实现gradle插件的方式之一),然后可以新建一个Kotlin配置文件来指定统一的版本号,如:

  • Config.kt
    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
    42
    private const val kotlinVersion = "1.2.21"
    private const val androidGradleVersion = "3.0.1"

    // Compile dependencies
    private const val supportVersion = "27.0.2"
    private const val ankoVersion = "0.10.4"
    private const val daggerVersion = "2.14.1"
    private const val retrofitVersion = "2.3.0"
    private const val okhttpVersion = "3.9.1"
    private const val eventBusVersion = "2.4.1"
    private const val picassoVersion = "2.5.2"
    private const val priorityJobQueueVersion = "2.0.1"

    // Unit tests
    private const val mockitoVersion = "2.13.0"

    object Config {
    object BuildPlugins {
    val androidGradle = "com.android.tools.build:gradle:$androidGradleVersion"
    val kotlinGradlePlugin = "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
    }

    object Android {
    val buildToolsVersion = "27.0.3"
    val minSdkVersion = 19
    val targetSdkVersion = 27
    val compileSdkVersion = 27
    val applicationId = "com.antonioleiva.bandhookkotlin"
    val versionCode = 1
    val versionName = "0.1"
    }

    object Libs {
    val kotlin_std = "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
    ...
    }

    object TestLibs {
    val junit = "junit:junit:4.12"
    ...
    }
    }

然后在需要的依赖的build.gradle脚本中这么写,

1
2
3
4
5
dependencies {
implementation(Config.Libs.kotlin_std)
...
androidTestImplementation(Config.TestLibs.mockito)
}

其他

关于Kotlin DSL写法的参考地址 https://github.com/gradle/kotlin-dsl