用Kotlin寫Android Gradle指令碼

歐陽鋒發表於2018-01-29

文 | 歐陽鋒

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工程:

用Kotlin寫Android Gradle指令碼

接下來,改造開始,Gradle Script Kotlin指令碼以.gradle.kts字尾結尾。因此,我們先將工程根目錄settings.gradle更名為settings.gradle.kts

用Kotlin寫Android Gradle指令碼

這個地方的錯誤有兩個原因:

  • 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檔案,這也是最複雜的一步,修改完字尾名後,你會看到整個指令碼全部被紅色標識錯誤:

用Kotlin寫Android Gradle指令碼

別慌!還是一樣的方式,這裡我們先將這裡的所有程式碼註釋掉。在最上方逐一對應修改,apply plugin部分修改為:

plugins {
    id("com.android.application")
}
複製程式碼

接下來,修改android {}閉包部分。這裡有兩個小技巧,由於目前IDE的支援不是很完善,在輸入的時候稍微等待一段時間,IDE會給出相應的提示。另外,如果沒有提示,例如android {}閉包就沒有任何提示,輸入完成後展開右側gradle皮膚,選擇gradle/buid setup/init,雙擊執行:

用Kotlin寫Android Gradle指令碼

在底部皮膚可以看到任務執行是否成功。注意,即使任務執行成功,指令碼依然可能被紅色標識,這是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使用者去掉./執行即可。

用Kotlin寫Android Gradle指令碼

最後的依賴部分,同樣地,全部修改為括號呼叫即可。這裡就不贅述了,文章的最後部分會提供操作視訊,在使用過程中有任何問題可以開啟操作視訊參考,如果依然不能解決,可以在文章下方給我留言,我會在第一時間給你答覆。修改後的內容如下:

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測試是否可以正常構建了:

用Kotlin寫Android Gradle指令碼

統一依賴管理

上面的步驟雖然完成了指令碼的轉換,但依賴的管理依然是混亂的,為了實現類似 Snake 工程的統一依賴管理,我們還需要做一些工作。

Gradle官方提供了使用 buildSrc 目錄實現自定義任務和外掛邏輯,這裡我們可以使用它完成依賴的統一處理,一個完整的buildSrc目錄結構如下:

用Kotlin寫Android Gradle指令碼

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,也歡迎你給我傳送私信訊息。

用Kotlin寫Android Gradle指令碼

本篇文章例子完整程式碼,請點選這裡:github.com/yuanhoujun/…

kts文件正在編寫當中,具體進度,請點這裡:github.com/gradle/kotl…

歡迎加入Kotlin交流群

如果你也喜歡Kotlin語言,歡迎加入我的Kotlin交流群: 329673958 ,一起來參與Kotlin語言的推廣工作。

學更多程式設計知識,掃描下方二維碼關注歐陽鋒工作室

歐陽鋒工作室

獲得更好閱讀體驗,請閱讀原文:www.jianshu.com/p/8fdfbcf35…

相關文章