Android應用開發中,離不開Gradle指令碼的構建。大部分Android開發同學忽視了指令碼的力量,甚至有很大一部分同學不知道Gradle指令碼是什麼,用什麼語言編寫的;當然,也有相當一部分同學知道Gradle指令碼是使用Groovy語言編寫的,但對於Groovy語言卻一竅不通,只是勉強可以看懂Gradle指令碼。正所謂,知其然,但並不知其所以然...
換個角度看問題,熟練掌握Gradle指令碼還需要精通Groovy語言,這對Android開發同學來說的確是一個不小的挑戰。這種Java + Groovy的開發套餐對於普通的Android開發者來說的確存在一定的知識斷層,顯而易見的是,部分同學寫的Gradle指令碼簡直“不堪入目”。時間回到去年5月份,Google IO大會上宣佈了一個重磅訊息,Android官方開始支援使用Kotlin語言進行應用開發。其實,在這個時間節點上,我已經在生產環境使用Kotlin開發Android將近一年。對於我來說,這無疑是一個讓人欣喜若狂的訊息。但,驚喜還遠遠不止這些,過了一段時間,我又看到了這篇文章 Kotlin Meets Gradle。很有詩意的標題:當Gradle邂逅Kotlin,文章的核心意思是:Gradle團隊正在嘗試使用Kotlin語言作為Gradle指令碼的官方開發語言。
我想,也許,Android開發者的春天就要到了!
Why use Kotlin ?
在寫Gradle指令碼的時候,最痛苦的莫過於沒有任何提示,唯一的除錯手段就是使用print方法列印除錯日誌。正如 Kotlin Meets Gradle 文中所說,當你使用Kotlin語言編寫Gradle指令碼的時候,你會發現一切都變得有趣起來。突然:
- 指令碼程式碼可以自動補全了
- 原始碼之間可以互相跳轉了
- 外掛原始碼更容易看懂了
- 重構(Refactoring)也可以支援了 ...
當然,驚喜還不止這些,當你開始決定使用Kotlin語言的時候,彷彿一切都變得美好了起來!
Let's start
好了,廢話不多說,接下來我們開始嘗試用Kotlin語言編寫Gradle指令碼。由於當前 kotlin-dsl 正處於預釋出狀態(kotlin-dsl的最新版本是0.14.2,對應Gradle外掛版本4.5),IDE的支援也不完善,為了更好的體驗該功能,推薦大家使用如下配置:
實驗室配置
作業系統: macOS 10.13.2
Android Studio: 3.1 Canary 9
Gradle Wrapper: 4.5
Gradle Plugin: 3.1.0-alpha9
Kotlin:1.2.21
操作步驟
首先,按照以往步驟建立一個Android工程:
接下來,改造開始,Gradle Script Kotlin指令碼以.gradle.kts
字尾結尾。因此,我們先將工程根目錄settings.gradle
更名為settings.gradle.kts
。
這個地方的錯誤有兩個原因:
- Kotlin語言中,單引號只能包裹字元,不能包裹字串
- Kotlin語言中,方法呼叫使用括號。僅在使用
infix
修飾的方法中可以省略括號。這裡顯然是一個正常呼叫方法。因此,我們修改為:
include("app")
複製程式碼
接下來,修改根目錄的build.gradle
指令碼,用同樣的方式修改字尾,方法修改為括號呼叫,修改後的內容如下:
buildscript {
repositories {
google()
jcenter()
}
dependencies {
// 這裡修改為括號呼叫即可
classpath("com.android.tools.build:gradle:3.0.1")
}
}
allprojects {
repositories {
google()
jcenter()
}
}
複製程式碼
注意:在修改字尾名稱的時候IDE會出現警告提示,這裡可以忽略,選擇continue即可。
由於我們手動修改了build.gradle
指令碼,為了保證工程可以使用這個指令碼,需要在settings.gradle.kts
中新增一行程式碼,讓Gradle知道使用build.gradle.kts
指令碼構建。因此,最後的settings.gradle.kts
程式碼如下:
include("app")
rootProject.buildFileName = "build.gradle.kts"
複製程式碼
最後一步,修改app模組build.gradle
檔案,這也是最複雜的一步,修改完字尾名後,你會看到整個指令碼全部被紅色標識錯誤:
別慌!還是一樣的方式,這裡我們先將這裡的所有程式碼註釋掉。在最上方逐一對應修改,apply plugin
部分修改為:
plugins {
id("com.android.application")
}
複製程式碼
接下來,修改android {}
閉包部分。這裡有兩個小技巧,由於目前IDE的支援不是很完善,在輸入的時候稍微等待一段時間,IDE會給出相應的提示。另外,如果沒有提示,例如android {}
閉包就沒有任何提示,輸入完成後展開右側gradle皮膚,選擇gradle/buid setup/init
,雙擊執行:
在底部皮膚可以看到任務執行是否成功。注意,即使任務執行成功,指令碼依然可能被紅色標識,這是IDE支援不完善導致的,可以忽略。
修改完成後的內容如下:
android {
compileSdkVersion(27)
buildToolsVersion("27.0.2")
defaultConfig {
applicationId = "com.youngfeng.kotlindsl"
minSdkVersion(15)
targetSdkVersion(27)
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
getByName("release") {
isMinifyEnabled = true
proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
}
}
}
複製程式碼
注意:你在使用的過程中,依然可能會遇到無論如何都不生效的問題。這個時候彆著急,使用./gradlew assembleDebug
命令除錯,檢視終端找到錯誤原因。Windows使用者去掉./
執行即可。
最後的依賴部分,同樣地,全部修改為括號呼叫即可。這裡就不贅述了,文章的最後部分會提供操作視訊,在使用過程中有任何問題可以開啟操作視訊參考,如果依然不能解決,可以在文章下方給我留言,我會在第一時間給你答覆。修改後的內容如下:
dependencies {
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
implementation("com.android.support:appcompat-v7:26.1.0")
implementation("com.android.support.constraint:constraint-layout:1.0.2")
testImplementation("junit:junit:4.12")
androidTestImplementation("com.android.support.test:runner:1.0.1")
androidTestImplementation("com.android.support.test.espresso:espresso-core:3.0.1")
}
複製程式碼
通過上面的步驟,從Groovy轉換到Kotlin的步驟已經全部完成,你可以在終端輸入./gradlew assembleDebug
測試是否可以正常構建了:
統一依賴管理
上面的步驟雖然完成了指令碼的轉換,但依賴的管理依然是混亂的,為了實現類似 Snake 工程的統一依賴管理,我們還需要做一些工作。
Gradle官方提供了使用 buildSrc 目錄實現自定義任務和外掛邏輯,這裡我們可以使用它完成依賴的統一處理,一個完整的buildSrc目錄結構如下:
Deps類中,可以這樣定義依賴結構:
object deps {
object plugin {
val gradle = "com.android.tools.build:gradle:3.1.0-alpha09"
val kotlin = "org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.21"
}
object kotlin {
val stdlibJre7 = "org.jetbrains.kotlin:kotlin-stdlib-jre7:1.2.21"
}
object android {
object support {
val compat = "com.android.support:appcompat-v7:27.0.2"
val constraintLayout = "com.android.support.constraint:constraint-layout:1.0.2"
}
object test {
val junit = "junit:junit:4.12"
val runner = "com.android.support.test:runner:1.0.1"
val espressoCore = "com.android.support.test.espresso:espresso-core:3.0.1"
}
}
}
複製程式碼
定義之後,我們就可以在指令碼中直接引用了:
dependencies {
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
implementation(deps.kotlin.stdlibJre7)
implementation(deps.android.support.compat)
implementation(deps.android.support.constraintLayout)
testImplementation(deps.android.test.junit)
androidTestImplementation(deps.android.test.runner)
androidTestImplementation(deps.android.test.espressoCore)
}
複製程式碼
是不是漂亮了許多?
至此,整個轉換過程就順利完成了,為了保證轉換的成功率,我推薦使用文章開頭的實驗室配置。如果版本過低,不保證可以轉換成功。最新版本的kotlin-dsl會跟隨最新版本的Gradle外掛釋出,因此一定要使用最新版本。另外,目前IDE對kts的支援依然不完善,即使正確的寫法也會報錯,這個一定要注意,不要被IDE欺騙了。
更詳細的操作,請看視訊教程
騰訊視訊:用Kotlin寫Android Gradle指令碼
一些建議
雖然使用Kotlin語言寫指令碼是一件非常美妙的事情,但目前依然存在一些問題:
- IDE支援不完善
- kotlin-dsl 正在快速開發中,語法變動較大
- 缺少官方文件
- 網際網路上缺少相關資料,遇到問題很難追蹤
因此,目前我並不推薦你在生產環境中使用,但可以作為日常學習練手之用。預計1.0版本的釋出在今年6月份左右,正式版本釋出後,我推薦你立即將Gradle指令碼轉換到Kotlin語言。
遇到問題,看這裡 ==>
在使用的過程中,按照文章同樣的步驟,你依然可能會遇到很多問題。因此,我為你整理了目前網際網路上可以參考的資料,你可以收藏這篇文章。遇到問題別慌,來這裡查詢答案。
關於kotlin-dsl的開發路線圖,請看這篇文章:blog.gradle.org/kotlin-scri…
如果你在使用過程中,遇到了任何問題,並且確定是 kotlin-dsl 的bug,請點這裡:github.com/gradle/kotl… 並推送 issue
如果你遇到了知識盲點,並且在Google找不到答案。可以來 Slack#gradle頻道反饋,我在 Slack 的暱稱是Scott Smith,也歡迎你給我傳送私信訊息。
本篇文章例子完整程式碼,請點選這裡:github.com/yuanhoujun/…
kts文件正在編寫當中,具體進度,請點這裡:github.com/gradle/kotl…
歡迎加入Kotlin交流群
如果你也喜歡Kotlin語言,歡迎加入我的Kotlin交流群: 329673958 ,一起來參與Kotlin語言的推廣工作。
學更多程式設計知識,掃描下方二維碼關注歐陽鋒工作室
獲得更好閱讀體驗,請閱讀原文:www.jianshu.com/p/8fdfbcf35…