Gradle Kotlin 遷移指南

最近寫了一些 Gradle 腳本,Groovy 十分糟糕的體驗讓我想嘗試把 Groovy 遷移到 Kotlin 上java

爲何不想用 Groovy

  • 幾乎沒有智能提示
  • 沒法直接查看 groovy api 的源碼
  • 上面兩條致使,一個 Android 開發者沒法快速上手 Gradle 來編寫一些複雜的腳本

Kotlin 編寫 Gradle 的優點

  • 靜態語言的全部優點
  • Kotlin DSL 的特性能夠像 Groovy 同樣簡潔
  • 完整的 IDE 支持
  • buildSrc 新特性能夠像管理 Java 文件同樣管理全部腳本

版本要求

  • JDK 1.8 及以上
  • Gradle 5.0 及以上
  • 最新版 Android Gradle 插件

開始遷移

首先,把你的 build.gradle 文件名改成 build.gradle.kts,( 後綴居然不是 kt )android

語法變化

儘管 Kotlin DSL 和 Groovy DSL 很像,可是仍是沒有脫離 Kotlin 的語法規則git

  1. 全部的 ' ' 變成 " ",由於 Kotlin 的字符串必須使用雙引號github

  2. 空格變成方法調用或者賦值,好比:api

    include ':app', ':basemodule', ':home', ':read', ':data', ':personalcenter'
    複製代碼

    改成app

    include(":app", ":basemodule", ":home", ":read", ":data", ":personalcenter")
    複製代碼

    defaultConfig {
      versionCode Build.versionCode
    }
    複製代碼

    改成jvm

    defaultConfig {
    	versionCode = Build.versionCode
    }
    複製代碼
  3. map的使用,例如:ide

    implementation fileTree(dir: 'libs', include: ['*.jar'])
    複製代碼

    改成gradle

    implementation(fileTree(mapOf("include" to listOf("*.jar"), "dir" to "libs")))
    複製代碼

其它API的變化

  1. pluginsui

    apply plugin: 'com.android.application'
    apply plugin: 'kotlin-android'
    apply plugin: 'kotlin-android-extensions'
    apply plugin: 'kotlin-kapt'
    複製代碼

    如今變成:

    plugins {
        id("com.android.application")
        kotlin("android")
        kotlin("kapt")
        kotlin("android.extensions")
    }
    複製代碼

    這裏的 kotlin這個方法頗有意思,能夠點進去看一下源碼:

    fun PluginDependenciesSpec.kotlin(module: String): PluginDependencySpec =
        id("org.jetbrains.kotlin.$module")
    複製代碼

    發現就是第一行 id 那個方法的擴展😆

  2. task

    原來的寫法:

    task clean(type: Delete) {
        delete rootProject.buildDir
    }
    複製代碼

    這裏寫法比較自由,可使用 ProjectExtensions 裏的 task 方法:

    task("clean", Delete::class) {
        delete(rootProject.buildDir)
    }
    複製代碼

    也能夠用 ProjectsDelegate 的 TaskContainer 的 register 方法:

    tasks.register("clean", Delete::class) {
        delete(rootProject.buildDir)
    }
    複製代碼
  3. buildType 原來的 release、debug 須要經過 getByName(String name, Action<? super T> configureAction) 這個方法來構建:

    buildTypes {
      getByName("release") {
        isMinifyEnabled = true
        isZipAlignEnabled = true
        isShrinkResources = true
        proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
      }
    }
    複製代碼

新特性 buildSrc

Gradle 5.0 以後推出了一個叫 buildSrc 的東西,簡單來講就是把你的腳本相關代碼放在一個文件夾裏單獨管理,build.gradle 最終能夠直接調用到這些代碼,這也是此次遷移最吸引個人一個特性。

目錄結構:

你會發現 buildSrc 就是一個普通的 module,有本身的 build.gradle,有 build 產物,文件結構也遵循src/main/kotlin(或者java)。

構建步驟

  1. 根目錄下新建一個 buildSrc 文件夾

  2. 新建 src/main/kotlin目錄

  3. 新建一個 build.gradle.kts 文件,內容以下:

    plugins {
        `kotlin-dsl`
    }
    
    repositories {
        // The org.jetbrains.kotlin.jvm plugin requires a repository
        // where to download the Kotlin compiler dependencies from.
        jcenter()
    }
    複製代碼

    同步一下便可開始編寫你的代碼

能夠作哪些事

最基礎的就是管理全部的依賴和版本號,好比

object Versions {
    const val support = "27.1.1"
    const val constraint = "1.1.3"
    const val lifecycle = "1.1.1"
    // ...
}
// ...
object Deps {
    object Support {
        val appCompat = "com.android.support:appcompat-v7:${Versions.support}"
        val constraint = "com.android.support.constraint:constraint-layout:${Versions.constraint}"
        val design = "com.android.support:design:${Versions.support}"
    }

    object Lifecycle {
        val extensions = "android.arch.lifecycle:extensions:${Versions.lifecycle}"
    }

    object Retrofit {
        val runtime = "com.squareup.retrofit2:retrofit:${Versions.retrofit}"
        val gson = "com.squareup.retrofit2:converter-gson:${Versions.retrofit}"
        val rxjava2 = "com.squareup.retrofit2:adapter-rxjava2:${Versions.retrofit}"
    }
    // ...
}
複製代碼

另外,還能夠把共有的依賴封裝進方法,分類管理你的各類 task 等等。

遷移過程當中遇到的一些問題

  • 不少 API 找不到,當你開始遷移一個 build.gradle 文件時,會發現一片紅色,不少 api 不識別,不要慌,由於有些api是編譯時生成的,並不包含在標準庫裏,當你把全部語法都改完以後從新編譯就會正常
  • Groovy 和 Kotlin 互通性,一些 groovy 腳本經過 apply from 在 kts 裏仍然能夠生效,可是想調用裏面的東西……基本不可能,全部要遷移的話,最好一次所有遷移掉

相關連接

相關文章
相關標籤/搜索