I’ve been writing Gradle scripts lately, and the awful experience with Groovy has made me want to try migrating Groovy to Kotlin

Why not use Groovy

  • There are few intelligent hints
  • You cannot view the source code of the Groovy API directly
  • As a result, an Android developer cannot learn Gradle quickly enough to write complex scripts

Advantages of Kotlin writing Gradle

  • All the advantages of static languages
  • The Kotlin DSL’s features can be as neat as Groovy’s
  • Full IDE support
  • The new buildSrc feature manages all scripts like Java files

Version for

  • JDK 1.8 and above
  • Gradle 5.0 or above
  • The latest Android Gradle plugin

Starting the migration

First, change your build.gradle file name to build.gradle. KTS.

Grammar changes

Although Kotlin DSLS are similar to Groovy DSLS, they do not deviated from Kotlin’s syntactic rules

  1. All ‘ ‘becomes “” because Kotlin’s string must be in double quotes

  2. Spaces become method calls or assignments, as in:

    include ':app'.':basemodule'.':home'.':read'.':data'.':personalcenter'
    Copy the code

    Instead of

    include(":app".":basemodule".":home".":read".":data".":personalcenter")
    Copy the code

    defaultConfig {
      versionCode Build.versionCode
    }
    Copy the code

    Instead of

    defaultConfig {
    	versionCode = Build.versionCode
    }
    Copy the code
  3. Use of map, for example:

    implementation fileTree(dir: 'libs'.include: ['*.jar'])
    Copy the code

    Instead of

    implementation(fileTree(mapOf("include" to listOf("*.jar"), "dir" to "libs")))
    Copy the code

Other API changes

  1. plugins

    apply plugin: 'com.android.application'
    apply plugin: 'kotlin-android'
    apply plugin: 'kotlin-android-extensions'
    apply plugin: 'kotlin-kapt'
    Copy the code

    Now it becomes:

    plugins {
        id("com.android.application")
        kotlin("android")
        kotlin("kapt")
        kotlin("android.extensions")}Copy the code

    Here kotlin this method is very interesting, you can click on the source code:

    fun PluginDependenciesSpec.kotlin(module: String): PluginDependencySpec =
        id("org.jetbrains.kotlin.$module")
    Copy the code

    The discovery is an extension of the method id in the first line 😆

  2. task

    Originally written:

    task clean(type: Delete) {
        delete rootProject.buildDir
    }
    Copy the code

    The task method in project Tensions can be used:

    task("clean", Delete::class) {
        delete(rootProject.buildDir)
    }
    Copy the code

    You can also use the ProjectsDelegate TaskContainer register method:

    tasks.register("clean", Delete::class) {
        delete(rootProject.buildDir)
    }
    Copy the code
  3. GetByName (String name, Action
    configureAction) this method builds:

    buildTypes {
      getByName("release") {
        isMinifyEnabled = true
        isZipAlignEnabled = true
        isShrinkResources = true
        proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")}}Copy the code

New features buildSrc

Gradle 5.0 comes with a feature called buildSrc, which simply puts your script-related code in a separate folder, and builds. Gradle can eventually call that code directly, which is one of the most interesting features of this migration for me.

Directory structure:

You’ll notice that buildSrc is a normal module with its own build.gradle, build artifacts, and a file structure that follows SRC /main/ Kotlin (or Java).

Build steps

  1. Create a new buildSrc folder in the root directory

  2. Create a new SRC /main/kotlin directory

  3. Create a new build.gradle. KTS file with the following contents:

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

    Sync up and start writing your code

What can be done

The most basic is to manage all dependencies and version numbers, such as

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}"
    }
    // ...
}
Copy the code

In addition, you can encapsulate common dependencies into methods, categorize your various tasks, and so on.

Some issues encountered during migration

  • Gradle file, you will find a red color. Many oF the apis are not recognized. Don’t panic, because some oF the apis are compiled at compile time and are not included in the standard library
  • Groovy and Kotlin are interoperable. Some Groovy scripts can still work in KTS with apply from, but want to call the stuff inside… Almost impossible. If you want to migrate everything, you’d better migrate it all at once

A link to the

  • Training project: github.com/howshea/Gee…

  • The migration of the official document: guides.gradle.org/migrating-b…

  • Reference source: github.com/DroidKaigi/…