第12章 使用 Kotlin 內建Gradle 開發
《Kotlin極簡教程》正式上架:
點選這裡 > 去京東商城購買閱讀
點選這裡 > 去天貓商城購買閱讀
非常感謝您親愛的讀者,大家請多支援!!!有任何問題,歡迎随時與我交流~
由于 Kotlin 具有豐富的功能,如一等函數和擴充方法等,是以它可以保留和改進 Gradle 建構腳本的最佳部分——包括簡明的聲明式文法以及輕松制作 DSL 的能力。
Gradle 團隊與 Kotlin 團隊密切合作,為 Gradle 開發了新的基于 Kotlin 腳本的建構配置語言,我們稱之為 Gradle Script Kotlin,支援使用 Kotlin 編寫建構和配置檔案。同時,還支援在 IDE 中實作自動完成和編譯檢查等功能。有了Gradle Script Kotlin,我們可以使用 Kotlin 來寫配置檔案,就跟寫普通代碼一樣。
我們在前面的章節中,已經有很多示例項目使用了 Gradle 來建構我們的 Kotlin 工程。本章我們将系統地來介紹一下使用 Kotlin 內建Gradle 開發的相關内容。
12.1 使用 Gradle 建構 Kotlin工程
12.1.1 kotlin-gradle 插件
為了用 Gradle 建構 Kotlin工程,我們需要設定好 kotlin-gradle 插件:
buildscript {
ext {
kotlinVersion = '1.1.3-2'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}")
...
}
}
apply plugin: 'kotlin'
并且添加 kotlin-stdlib 依賴:
dependencies {
compile("org.jetbrains.kotlin:kotlin-stdlib-jre8:${kotlinVersion}")
compile("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}")
}
當然,這些操作在我們建立項目的時候,通常我們隻需要選擇相應的選項, IntelliJ IDEA 就會直接幫我們完成了基本的配置了。
我們使用
kotlin-gradle-plugin
編譯 Kotlin 源代碼和子產品。使用的 Kotlin 版本通常定義為
kotlinVersion
屬性。
針對 JVM,我們需要應用 Kotlin 插件:
apply plugin: "kotlin"
12.1.2 Kotlin 與 Java 混合程式設計
Kotlin 源代碼可以與同一個檔案夾或不同檔案夾中的 Java 源代碼混用。預設約定是使用不同的檔案夾:
sourceSets {
main.kotlin.srcDirs += 'src/main/kotlin'
main.java.srcDirs += 'src/main/java'
}
如果使用預設的目錄,上面的配置可以省去不寫。
如果不使用預設約定,那麼應該更新相應的 sourceSets 屬性
sourceSets {
main.kotlin.srcDirs += 'src/main/myKotlin'
main.java.srcDirs += 'src/main/myJava'
}
12.1.3 配置 Gradle JavaScript 項目
當針對 JavaScript 時,須應用不同的插件:
apply plugin: "kotlin2js"
除了輸出的 JavaScript 檔案,該插件預設會建立一個帶二進制描述符的額外 JS 檔案。
如果是建構其他 Kotlin 子產品可以依賴的可重用庫,那麼該檔案是必需的,并且與轉換結果一起分發。
二進制描述符檔案的生成由
kotlinOptions.metaInfo
選項控制:
compileKotlin2Js {
kotlinOptions.metaInfo = true
}
提示:示例工程可以參考
https://github.com/EasyKotlin/chapter2_hello_world_kotlin2js12.1.4 配置 Gradle Android項目
Android 的 Gradle 模型與普通 Gradle 有點不同,是以如果我們要建構一個用 Kotlin 編寫的 Android 項目,我們需要用 kotlin-android 插件取代 kotlin 插件:
buildscript {
ext.kotlin_version = '1.1.2-4'
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
通常我們使用 Android Studio,都是生成一個帶 app 子項目的工程。多項目配置的實作通常是在一個根項目路徑下将所有項目作為子檔案夾包含進去。例如我們在項目根路徑下面的settings.gradle中如下配置:
include ':app'
每一個子項目都擁有自己的build.gradle檔案來聲明自己如何建構。
例如,我們在子項目app的建構配置檔案 build.gradle 中一個完整的配置如下:
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "com.kotlin.easy.kotlinandroid"
minSdkVersion 14
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
testCompile 'junit:junit:4.12'
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
}
repositories {
mavenCentral()
}
其中,
apply plugin: 'kotlin-android' 是 Kotlin Android 插件。
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" 是 Kotlin 運作标準庫。
另外, Android Studio 預設加載源碼的目錄是
src/main/java
,如果想指定 Kotlin 代碼在
src/main/kotln
目錄,可以在 android 下添加以下内容:
android {
……
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
}
提示: 關于 Kotlin Android 的 Gradle 完整配置執行個體可參考
https://github.com/EasyKotlin/KotlinAndroid。
12.1.5 配置Kotlin 标準庫依賴
除了上面的
kotlin-gradle-plugin
依賴之外,我們還需要添加 Kotlin 标準庫的依賴:
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib"
}
如果針對 JavaScript,使用
compile "org.jetbrains.kotlin:kotlin-stdlib-js"
替代之。
如果是針對 JDK 7 或 JDK 8,那麼可以使用擴充版本的 Kotlin 标準庫,其中包含為新版 JDK 增加的額外的擴充函數。使用以下依賴之一來取代
kotlin-stdlib
:
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7"
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8"
如果項目中使用 Kotlin 反射,添加反射依賴:
compile "org.jetbrains.kotlin:kotlin-reflect"
如果項目中使用測試架構,我們添加相應的測試庫依賴:
testCompile "org.jetbrains.kotlin:kotlin-test"
testCompile "org.jetbrains.kotlin:kotlin-test-junit"
12.1.6 增量編譯
Kotlin 支援 Gradle 中可選的增量編譯。增量編譯跟蹤建構之間源檔案的改動,是以隻有受這些改動影響的檔案才會被編譯。從 Kotlin 1.1.1 起,預設啟用增量編譯。
12.1.7 編譯器選項
要指定附加的編譯選項,可以使用 Kotlin 編譯任務compileKotlin的
kotlinOptions
配置單個任務示例:
compileKotlin {
kotlinOptions {
suppressWarnings = true
}
}
12.2 使用 Kotlin 編寫建構和配置檔案
一個基于 Kotlin 來寫 Gradle 建構腳本及插件的方式可能會是什麼樣的? 它對團隊的幫助如何——尤其是大型團隊——加快工作速度并編寫結構更好、更易于維護的建構腳本?
這些可能性非常誘人。
因為 Kotlin 是一種靜态類型語言,在 IDEA 和 Eclipse 中都有深入的支援,是以可以從自動補全到重構,以及其間的一切都能為 Gradle 使用者提供适當的 IDE 支援。 而且由于 Kotlin 具有豐富的功能,如一等函數和擴充方法,是以它可以保留和改進 Gradle 建構腳本的最佳部分——包括簡明的聲明式文法以及輕松制作 DSL 的能力。
Gradle 團隊認真地考察了這些可能性,與 Kotlin 團隊密切合作,為 Gradle 開發一種新的基于 Kotlin 的建構語言——我們稱之為 Gradle Script Kotlin。
下面我們就來簡要介紹一下使用 Kotlin 腳本來編寫 Gradle 的配置檔案。
我們就以上一章中的 chapter11_kotlin_springboot 工程為例。
首先我們在根目錄下建立一個settings.gradle 配置檔案:
rootProject.name = 'chapter11_kotlin_springboot'
rootProject.buildFileName = 'build.gradle.kts'
指定 gradle 建構檔案名是 'build.gradle.kts' 。
然後,我們建立 'build.gradle.kts' , 完整的内容如下:
buildscript {
val kotlinVersion = "1.1.3-2"
val springBootVersion = "2.0.0.M2"
extra["kotlinVersion"] = kotlinVersion
repositories {
mavenCentral()
maven { setUrl("https://repo.spring.io/snapshot") }
maven { setUrl("https://repo.spring.io/milestone") }
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
classpath("org.jetbrains.kotlin:kotlin-allopen:$kotlinVersion")
}
}
apply {
plugin("kotlin")
plugin("kotlin-spring")
plugin("eclipse")
plugin("org.springframework.boot")
plugin("io.spring.dependency-management")
}
version = "0.0.1-SNAPSHOT"
configure<JavaPluginConvention> {
setSourceCompatibility(1.8)
setTargetCompatibility(1.8)
}
repositories {
mavenCentral()
maven { setUrl("https://repo.spring.io/snapshot") }
maven { setUrl("https://repo.spring.io/milestone") }
}
val kotlinVersion = extra["kotlinVersion"] as String
dependencies {
compile("org.springframework.boot:spring-boot-starter-actuator")
compile("org.springframework.boot:spring-boot-starter-data-jpa")
compile("org.springframework.boot:spring-boot-starter-freemarker")
compile("org.springframework.boot:spring-boot-starter-web")
compile("org.jetbrains.kotlin:kotlin-stdlib-jre8:${kotlinVersion}")
compile("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}")
runtime("org.springframework.boot:spring-boot-devtools")
runtime("mysql:mysql-connector-java")
testCompile("org.springframework.boot:spring-boot-starter-test")
}
提示: 按照上述步驟,建立完檔案build.gradle.kts後,IDEA 可能識别不了這些 DSL 函數,這個時候我們重新開機一下 IDEA 即可(這是一個 bug,後面會修複)。
這裡面的 Gradle DSL 的相關函數與類都在 Gradle 軟體包的 lib 目錄下: lib/gradle-script-kotlin-(版本号).jar 。我們簡單用下面的表格說明:
函數(類) | 對應的gradle-script-kotlin代碼 |
---|---|
buildscript | open fun buildscript(@Suppress("unused_parameter") block: ScriptHandlerScope.() -> Unit) = Unit |
repositories | fun ScriptHandler.repositories(configuration: RepositoryHandler.() -> Unit) =repositories.configuration() |
buildscript.dependencies | DependencyHandlerScope(scriptHandler.dependencies) |
configure | inline fun <reified T : Any> Project.configure(noinline configuration: T.() -> Unit) |
Project.dependencies | DependencyHandlerScope(dependencies).configuration() |
也就是說,其實這些配置函數背後都是由 Gradle 的 DSL 來實作的。
其實,這些配置文法看起跟 Groovy 的很像。例如:
Groovy :
repositories {
mavenCentral()
maven { url "https://repo.spring.io/snapshot" }
maven { url "https://repo.spring.io/milestone" }
}
Kotlin:
repositories {
mavenCentral()
maven { setUrl("https://repo.spring.io/snapshot") }
maven { setUrl("https://repo.spring.io/milestone") }
}
再例如:
Groovy:
sourceCompatibility = 1.8
targetCompatibility = 1.8
configure<JavaPluginConvention> {
setSourceCompatibility(1.8)
setTargetCompatibility(1.8)
}
提示: 本節示例工程源碼
https://github.com/EasyKotlin/chapter11_kotlin_springboot/tree/build.gradle.kts本章小結
本章我們簡要介紹了使用 Kotlin 內建 Gradle 開發過程中的一些常用的配置方法。Gradle 是一個非常好用的建構工具,當我們的 Kotlin 工程的配置檔案也是 Kotlin 代碼的時候,我們的工作又更加單純了許多,隻需要專注 Kotlin 即可。
在下一章中,我們将學習使用 Kotlin 和 Anko 來進行Android開發的相關内容。