Di chuyển cấu hình bản dựng từ Groovy sang Kotlin

Trình bổ trợ Android cho Gradle 4.0 đã bổ sung tính năng hỗ trợ sử dụng Kotlin trong cấu hình bản dựng Gradle để thay thế cho Groovy, ngôn ngữ lập trình được dùng theo truyền thống trong các tệp cấu hình Gradle.

Kotlin được ưu tiên hơn Groovy để viết tập lệnh Gradle vì Kotlin dễ đọc hơn và cung cấp khả năng kiểm tra thời gian biên dịch cũng như hỗ trợ IDE tốt hơn.

Mặc dù Kotlin hiện có khả năng tích hợp vào trình soạn thảo mã của Android Studio tốt hơn so với Groovy, nhưng các bản dựng sử dụng Kotlin có xu hướng chậm hơn các bản dựng sử dụng Groovy. Vì vậy, hãy cân nhắc hiệu suất bản dựng khi quyết định có di chuyển hay không.

Trang này cung cấp thông tin cơ bản về cách chuyển đổi các tệp bản dựng Gradle của ứng dụng Android từ Groovy sang Kotlin. Để tham khảo hướng dẫn di chuyển toàn diện hơn, hãy xem tài liệu chính thức của Gradle.

Lịch trình

Kể từ Android Studio Giraffe, các dự án mới sẽ sử dụng Kotlin DSL (build.gradle.kts) theo mặc định cho cấu hình bản dựng. Điều này mang lại trải nghiệm chỉnh sửa tốt hơn so với Groovy DSL (build.gradle) với tính năng làm nổi bật cú pháp, hoàn tất mã và điều hướng đến các nội dung khai báo. Để tìm hiểu thêm, hãy xem bài viết Gradle Kotlin DSL Primer.

Thuật ngữ thường gặp

DSL Kotlin: Dùng để chủ yếu tham chiếu đến DSL Kotlin của trình bổ trợ Android cho Gradle hoặc đôi khi đến DSL Kotlin dựa trên công cụ Gradle cơ bản.

Trong hướng dẫn di chuyển này, "Kotlin" và "Kotlin DSL" được dùng thay thế cho nhau. Tương tự, "Groovy" và "Groovy DSL" được sử dụng thay thế cho nhau.

Đặt tên tệp tập lệnh

Tên của đuôi tệp tập lệnh dựa trên ngôn ngữ của tệp bản dựng:

  • Các tệp bản dựng Gradle viết trong Groovy sử dụng đuôi tệp .gradle.
  • Các tệp bản dựng Gradle viết trong Kotlin sử dụng đuôi tệp .gradle.kts.

Chuyển đổi cú pháp

Có một số khác biệt chung về cú pháp giữa Groovy và Kotlin, vì vậy, bạn cần áp dụng những thay đổi này trong các tập lệnh bản dựng.

Thêm dấu ngoặc đơn vào lệnh gọi phương thức

Groovy cho phép bạn bỏ qua dấu ngoặc đơn trong các lệnh gọi phương thức, trong khi Kotlin yêu cầu các dấu ngoặc đơn đó. Để di chuyển cấu hình của bạn, hãy thêm dấu ngoặc đơn vào các loại lệnh gọi phương thức này. Mã này cho biết cách định cấu hình một chế độ cài đặt trong Groovy:

compileSdkVersion 30

Đây là mã tương tự được viết bằng Kotlin:

compileSdkVersion(30)

Thêm = vào lệnh gọi chỉ định

Groovy DSL cho phép bạn bỏ qua toán tử chỉ định = khi chỉ định thuộc tính, trong khi Kotlin yêu cầu toán tử đó. Mã này cho biết cách chỉ định các thuộc tính trong Groovy:

java {
    sourceCompatibility JavaVersion.VERSION_17
    targetCompatibility JavaVersion.VERSION_17
}

Mã này cho biết cách chỉ định các thuộc tính trong Kotlin:

java {
    sourceCompatibility = JavaVersion.VERSION_17
    targetCompatibility = JavaVersion.VERSION_17
}

Chuyển đổi chuỗi

Dưới đây là những điểm khác biệt về chuỗi giữa Groovy và Kotlin:

  • Đưa chuỗi vào dấu ngoặc kép: Mặc dù Groovy cho phép xác định các chuỗi bằng cách sử dụng dấu ngoặc đơn, nhưng Kotlin yêu cầu phải dùng dấu ngoặc kép.
  • Loại nội suy chuỗi trên biểu thức dấu chấm: Trong Groovy, bạn chỉ có thể sử dụng tiền tố $ để nội suy chuỗi trên các biểu thức dấu chấm, nhưng với Kotlin, bạn phải gói các biểu thức dấu chấm bằng dấu ngoặc nhọn. Ví dụ: trong Groovy, bạn có thể sử dụng $project.rootDir như minh hoạ trong đoạn mã sau:

        myRootDirectory = "$project.rootDir/tools/proguard-rules-debug.pro"
        

    Tuy nhiên trong Kotlin, mã trước đó gọi toString() trên project, chứ không phải trên project.rootDir. Để nhận giá trị của thư mục gốc, hãy gói biến ${project.rootDir} vào dấu ngoặc nhọn:

        myRootDirectory = "${project.rootDir}/tools/proguard-rules-debug.pro"
        

    Để tìm hiểu thêm, hãy xem phần Mẫu chuỗi trong tài liệu về Kotlin.

Đổi tên đuôi tệp

Nối .kts vào từng tệp bản dựng khi bạn di chuyển nội dung của tệp này. Ví dụ: chọn một tệp bản dựng, chẳng hạn như tệp settings.gradle. Đổi tên tệp thành settings.gradle.kts rồi chuyển đổi nội dung của tệp sang Kotlin. Hãy đảm bảo rằng dự án của bạn vẫn biên dịch sau khi di chuyển từng tệp bản dựng.

Hãy di chuyển các tệp nhỏ nhất trước, tích luỹ kinh nghiệm rồi mới di chuyển. Bạn có thể kết hợp các tệp bản dựng Kotlin và Groovy trong một dự án, vì vậy, hãy dành thời gian để di chuyển cẩn thận.

Thay thế def bằng val hoặc var

Thay thế def bằng val hoặc var, đây là cách bạn xác định các biến trong Kotlin. Đây là một nội dung khai báo biến trong Groovy:

def building64Bit = false

Đây là mã tương tự được viết bằng Kotlin:

val building64Bit = false

Thêm tiền tố is vào các thuộc tính boolean

Groovy sử dụng logic suy luận thuộc tính dựa trên tên thuộc tính. Đối với một thuộc tính boolean foo, các phương thức suy luận của thuộc tính đó có thể là getFoo, setFoo hoặc isFoo. Do đó, sau khi chuyển đổi sang Kotlin, bạn cần thay đổi tên thuộc tính thành các phương thức suy luận không được Kotlin hỗ trợ. Ví dụ, đối với các phần tử boolean DSL buildTypes, bạn cần thêm tiền tố is vào các phần tử đó. Mã này cho biết cách đặt các thuộc tính boolean trong Groovy:

android {
    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            ...
        }
        debug {
            debuggable true
            ...
        }
    ...

Sau đây là mã tương tự trong Kotlin. Xin lưu ý rằng các thuộc tính đều có tiền tố is.

android {
    buildTypes {
        getByName("release") {
            isMinifyEnabled = true
            isShrinkResources = true
            ...
        }
        getByName("debug") {
            isDebuggable = true
            ...
        }
    ...

Chuyển đổi danh sách và bản đồ

Danh sách và bản đồ trong Groovy và Kotlin được xác định bằng cú pháp khác. Groovy sử dụng [], trong khi Kotlin gọi các phương thức tạo bộ sưu tập một cách rõ ràng bằng listOf hoặc mapOf. Hãy nhớ thay thế [] bằng listOf hoặc mapOf khi di chuyển.

Dưới đây là cách xác định danh sách trong Groovy so với Kotlin:

jvmOptions += ["-Xms4000m", "-Xmx4000m", "-XX:+HeapDumpOnOutOfMemoryError</code>"]

Đây là mã tương tự được viết bằng Kotlin:

jvmOptions += listOf("-Xms4000m", "-Xmx4000m", "-XX:+HeapDumpOnOutOfMemoryError")

Dưới đây là cách xác định bản đồ trong Groovy so với Kotlin:

def myMap = [key1: 'value1', key2: 'value2']

Đây là mã tương tự được viết bằng Kotlin:

val myMap = mapOf("key1" to "value1", "key2" to "value2")

Định cấu hình loại bản dựng

Trong DSL Kotlin, chỉ có các loại bản phát hành và gỡ lỗi được cung cấp ngầm. Tất cả các loại bản dựng tuỳ chỉnh khác phải được tạo theo cách thủ công.

Trong Groovy, bạn có thể sử dụng bản gỡ lỗi, bản phát hành và một số loại bản dựng khác mà không cần tạo các loại bản dựng đó trước. Đoạn mã sau đây cho thấy cấu hình có các loại bản dựng debug, releasebenchmark trong Groovy.

buildTypes {
 debug {
   ...
 }
 release {
   ...
 }
 benchmark {
   ...
 }
}

Để tạo cấu hình tương đương trong Kotlin, bạn phải tạo loại bản dựng benchmark một cách rõ ràng.

buildTypes {
 debug {
   ...
 }

 release {
   ...
 }
 register("benchmark") {
    ...
 }
}

Di chuyển từ tập lệnh buildscript sang khối trình bổ trợ

Nếu bản dựng của bạn sử dụng khối buildscript {} để thêm trình bổ trợ vào dự án, thì bạn nên tái cấu trúc để sử dụng khối plugins {}. Khối plugins {} giúp bạn dễ dàng áp dụng các trình bổ trợ hơn và hoạt động tốt với danh mục phiên bản.

Ngoài ra, khi bạn sử dụng khối plugins {} trong các tệp bản dựng, Android Studio sẽ biết được ngữ cảnh ngay cả khi bản dựng không hoạt động được. Ngữ cảnh này giúp sửa tệp Kotlin DSL vì qua đó, Studio IDE có thể tiến hành hoàn tất mã và cung cấp thêm các nội dung đề xuất hữu ích.

Tìm ID trình bổ trợ

Mặc dù khối buildscript {} thêm các trình bổ trợ vào classpath của bản dựng bằng cách sử dụng tọa độ Maven của trình bổ trợ (ví dụ: com.android.tools.build:gradle:7.4.0), còn khối plugins {} sử dụng mã nhận dạng trình bổ trợ.

Đối với hầu hết các trình bổ trợ, mã nhận dạng trình bổ trợ là chuỗi được dùng khi bạn áp dụng các trình bổ trợ này bằng apply plugin. Ví dụ: các mã trình bổ trợ sau đây là một phần của Trình bổ trợ Android cho Gradle:

  • com.android.application
  • com.android.library
  • com.android.lint
  • com.android.test

Bạn có thể tìm thấy danh sách trình bổ trợ đầy đủ trong Kho lưu trữ Google Maven.

Nhiều mã nhận dạng trình bổ trợ có thể tham chiếu đến các trình bổ trợ Kotlin. Bạn nên sử dụng mã trình bổ trợ không được đặt tên và tái cấu trúc từ cách viết tắt thành mã trình bổ trợ được đặt tên trong vùng chứa tên theo bảng sau:

Mã trình bổ trợ viết tắt ID trình bổ trợ được đặt tên
kotlin org.jetbrains.kotlin.jvm
kotlin-android org.jetbrains.kotlin.android
kotlin-kapt org.jetbrains.kotlin.kapt
kotlin-parcelize org.jetbrains.kotlin.plugin.parcelize

Bạn cũng có thể tìm kiếm các trình bổ trợ trên Cổng trình bổ trợ Gradle, Kho lưu trữ trung tâm MavenKho lưu trữ Google Maven. Hãy đọc bài viết Phát triển trình bổ trợ Gradle tuỳ chỉnh để tìm hiểu thêm về cách hoạt động của mã nhận dạng trình bổ trợ.

Tái cấu trúc

Sau khi biết ID của trình bổ trợ mà mình sử dụng, hãy thực hiện các bước sau:

  1. Nếu bạn vẫn còn kho lưu trữ cho các trình bổ trợ được khai báo trong khối buildscript {}, hãy di chuyển các trình bổ trợ đó sang tệp settings.gradle.

  2. Thêm các trình bổ trợ vào khối plugins {} trong tệp build.gradle cấp cao nhất. Bạn cần chỉ định mã nhận dạng và phiên bản của trình bổ trợ tại đây. Nếu không cần áp dụng trình bổ trợ cho dự án gốc, hãy sử dụng apply false.

  3. Xoá các mục nhập classpath khỏi tệp build.gradle.kts cấp cao nhất.

  4. Áp dụng các trình bổ trợ bằng cách thêm các trình bổ trợ đó vào khối plugins {} trong tệp build.gradle ở cấp mô-đun. Bạn chỉ cần chỉ định mã nhận dạng của trình bổ trợ tại đây vì phiên bản này được kế thừa từ dự án gốc.

  5. Xoá lệnh gọi apply plugin cho trình bổ trợ khỏi tệp build.gradle ở cấp mô-đun.

Ví dụ: cách thiết lập này sử dụng khối buildscript {}:

// Top-level build.gradle file
buildscript {
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
    dependencies {
        classpath("com.android.tools.build:gradle:7.4.0")
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.0")
        ...
    }
}

// Module-level build.gradle file
apply(plugin: "com.android.application")
apply(plugin: "kotlin-android")

Đây là cách thiết lập tương đương bằng cách sử dụng khối plugins {}:

// Top-level build.gradle file
plugins {
   id 'com.android.application' version '7.4.0' apply false
   id 'org.jetbrains.kotlin.android' version '1.8.0' apply false
   ...
}

// Module-level build.gradle file
plugins {
   id 'com.android.application'
   id 'org.jetbrains.kotlin.android'
   ...
}

// settings.gradle
pluginManagement {
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
}

Chuyển đổi khối trình bổ trợ

Việc áp dụng các trình bổ trợ trong khối plugins {} cũng tương tự như trong Groovy và Kotlin. Mã sau đây cho biết cách áp dụng trình bổ trợ trong Groovy khi bạn sử dụng danh mục phiên bản:

// Top-level build.gradle file
plugins {
   alias libs.plugins.android.application apply false
   ...
}

// Module-level build.gradle file
plugins {
   alias libs.plugins.android.application
   ...
}

Mã sau đây cho biết cách thực hiện tương tự trong Kotlin:

// Top-level build.gradle.kts file
plugins {
   alias(libs.plugins.android.application) apply false
   ...
}

// Module-level build.gradle.kts file
plugins {
   alias(libs.plugins.android.application)
   ...
}

Mã sau đây cho biết cách áp dụng trình bổ trợ trong Groovy khi bạn không sử dụng danh mục phiên bản:

// Top-level build.gradle file
plugins {
   id 'com.android.application' version '7.3.0' apply false
   ...
}

// Module-level build.gradle file
plugins {
   id 'com.android.application'
   ...
}

Mã sau đây cho biết cách thực hiện tương tự trong Kotlin:

// Top-level build.gradle.kts file
plugins {
   id("com.android.application") version "7.3.0" apply false
   ...
}

// Module-level build.gradle.kts file
plugins {
   id("com.android.application")
   ...
}

Để biết thêm thông tin chi tiết về khối plugins {}, hãy xem phần Áp dụng trình bổ trợ trong tài liệu về Gradle.

Khác

Đối với mã mẫu Kotlin cho các chức năng khác, hãy xem các trang tài liệu sau:

Vấn đề đã biết

Hiện tại, một vấn đề đã biết là tốc độ bản dựng có thể chậm hơn trong Kotlin so với trong Groovy.

Cách báo cáo vấn đề

Để biết hướng dẫn về cách cung cấp thông tin chúng tôi cần nhằm phân loại vấn đề của bạn, hãy xem phần Thông tin chi tiết về công cụ bản dựng và lỗi Gradle. Sau đó, gửi lỗi bằng công cụ theo dõi lỗi công khai của Google.

Tài nguyên khác

Để xem ví dụ cách thức hoạt động của các tệp bản dựng trên Gradle viết bằng Kotlin, hãy xem ứng dụng mẫu Now In Android trên GitHub.