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 里仍然能够生效,可是想调用里面的东西……基本不可能,全部要迁移的话,最好一次所有迁移掉

相关连接

相关文章
相关标签/搜索