ย้ายข้อมูลการกำหนดค่าบิลด์จาก Groovy ไปยัง Kotlin

ปลั๊กอิน Android Gradle 4.0 เพิ่มการรองรับการใช้ Kotlin ในการกำหนดค่าบิลด์ Gradle เพื่อแทนที่ Groovy ซึ่งเป็นภาษาโปรแกรมที่ใช้ในไฟล์การกำหนดค่า Gradle มาอย่างยาวนาน

เราขอแนะนำให้ใช้ Kotlin แทน Groovy ในการเขียนสคริปต์ Gradle เนื่องจาก Kotlin อ่านง่ายกว่า รวมถึงมีการตรวจสอบและการสนับสนุน IDE ที่ดียิ่งขึ้นเมื่อคอมไพล์

แม้ว่าปัจจุบัน Kotlin จะผสานรวมกับเครื่องมือแก้ไขโค้ดของ Android Studio ได้ดีกว่า Groovy แต่บิลด์ที่ใช้ Kotlin มักจะช้ากว่าบิลด์ที่ใช้ Groovy ดังนั้นให้พิจารณาประสิทธิภาพของบิลด์เมื่อตัดสินใจว่าจะย้ายข้อมูลหรือไม่

หน้านี้ให้ข้อมูลเบื้องต้นเกี่ยวกับการแปลงไฟล์บิลด์ Gradle ของแอป Android จาก Groovy เป็น Kotlin ดูคำแนะนำการย้ายข้อมูลที่ครอบคลุมมากขึ้นได้ในเอกสารประกอบอย่างเป็นทางการของ Gradle

ไทม์ไลน์

ตั้งแต่ Android Studio Giraffe เป็นต้นไป โปรเจ็กต์ใหม่จะใช้ Kotlin DSL (build.gradle.kts) โดยค่าเริ่มต้นสำหรับการกำหนดค่าบิลด์ ซึ่งให้ประสบการณ์การแก้ไขที่ดีกว่า Groovy DSL (build.gradle) ด้วยการไฮไลต์ไวยากรณ์ การเติมโค้ดอัตโนมัติ และการไปยังประกาศ ดูข้อมูลเพิ่มเติมได้ที่Gradle Kotlin DSL Primer

คำศัพท์ทั่วไป

Kotlin DSL: หมายถึง Kotlin DSL ของปลั๊กอิน Gradle สำหรับ Android เป็นหลัก หรือบางครั้งอาจหมายถึง Kotlin DSL ของ Gradle ที่อยู่เบื้องหลัง

ในคู่มือการย้ายข้อมูลนี้ เราจะใช้คำว่า "Kotlin" และ "Kotlin DSL" แทนกันได้ ในทำนองเดียวกัน "Groovy" และ "Groovy DSL" ก็ใช้แทนกันได้

การตั้งชื่อไฟล์สคริปต์

ชื่อนามสกุลไฟล์สคริปต์จะอิงตามภาษาที่เขียนไฟล์บิลด์ ดังนี้

  • ไฟล์บิลด์ Gradle ที่เขียนด้วย Groovy จะใช้นามสกุลไฟล์ .gradle
  • ไฟล์บิลด์ Gradle ที่เขียนด้วย Kotlin จะใช้นามสกุลไฟล์ .gradle.kts

แปลงไวยากรณ์

ไวยากรณ์ของ Groovy และ Kotlin มีความแตกต่างกันอยู่บ้าง คุณจึงต้องใช้การเปลี่ยนแปลงเหล่านี้กับสคริปต์บิลด์ทั้งหมด

เพิ่มวงเล็บเหลี่ยมในการเรียกใช้เมธอด

Groovy ให้คุณละเว้นวงเล็บในการเรียกใช้เมธอดได้ แต่ Kotlin ต้องใช้วงเล็บ หากต้องการย้ายข้อมูลการกําหนดค่า ให้เพิ่มวงเล็บเหลี่ยมในการเรียกใช้เมธอดประเภทเหล่านี้ โค้ดนี้แสดงวิธีกําหนดการตั้งค่าใน Groovy

compileSdkVersion 30

นี่เป็นโค้ดเดียวกันที่เขียนด้วย Kotlin

compileSdkVersion(30)

เพิ่ม = ลงในคําเรียกงาน

Groovy DSL ให้คุณละเว้นโอเปอเรเตอร์การกําหนดค่า = เมื่อกําหนดค่าพร็อพเพอร์ตี้ได้ แต่ Kotlin ต้องใช้โอเปอเรเตอร์นี้ โค้ดนี้แสดงวิธีกำหนดพร็อพเพอร์ตี้ใน Groovy

java {
    sourceCompatibility JavaVersion.VERSION_17
    targetCompatibility JavaVersion.VERSION_17
}

โค้ดนี้แสดงวิธีกําหนดพร็อพเพอร์ตี้ใน Kotlin

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

แปลงสตริง

ความแตกต่างของสตริงระหว่าง Groovy กับ Kotlin มีดังนี้

  • เครื่องหมายคำพูดคู่สำหรับสตริง: แม้ว่า Groovy จะอนุญาตให้กำหนดสตริงโดยใช้เครื่องหมายคำพูดเดี่ยว แต่ Kotlin ต้องใช้เครื่องหมายคำพูดคู่
  • การแทรกสตริงในนิพจน์ที่มีจุด: ใน Groovy คุณจะใช้แค่คำนำหน้า $ สำหรับการแทรกสตริงในนิพจน์ที่มีจุดได้ แต่ Kotlin กำหนดให้ต้องใส่วงเล็บปีกกาครอบนิพจน์ที่มีจุด เช่น ใน Groovy คุณสามารถใช้ $project.rootDir ดังที่แสดงในข้อมูลโค้ดต่อไปนี้

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

    อย่างไรก็ตาม ใน Kotlin โค้ดก่อนหน้าจะเรียก toString() on project ไม่ใช่ on project.rootDir หากต้องการรับค่าของไดเรกทอรีรูท ให้ใส่วงเล็บปีกการอบนิพจน์ ${project.rootDir}

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

    ดูข้อมูลเพิ่มเติมได้ที่เทมเพลตสตริงในเอกสารประกอบของ Kotlin

เปลี่ยนชื่อนามสกุลไฟล์

ต่อท้าย .kts ลงท้ายไฟล์บิลด์แต่ละไฟล์ขณะที่ย้ายข้อมูลเนื้อหา เช่น เลือกไฟล์บิลด์ เช่น ไฟล์ settings.gradle เปลี่ยนชื่อไฟล์เป็น settings.gradle.kts แล้วแปลงเนื้อหาของไฟล์เป็น Kotlin ตรวจสอบว่าโปรเจ็กต์ยังคงคอมไพล์ได้หลังจากการย้ายข้อมูลไฟล์บิลด์แต่ละไฟล์

ย้ายข้อมูลไฟล์ขนาดเล็กที่สุดก่อน แล้วค่อยๆ ย้ายข้อมูลไฟล์อื่นๆ คุณอาจใช้ไฟล์บิลด์ Kotlin และ Groovy ร่วมกันในโปรเจ็กต์ได้ ดังนั้นโปรดใช้เวลาในการย้ายอย่างระมัดระวัง

แทนที่ def ด้วย val หรือ var

แทนที่ def ด้วย val หรือ var ซึ่งเป็นวิธีกำหนดตัวแปรใน Kotlin นี่คือการประกาศตัวแปรใน Groovy

def building64Bit = false

นี่เป็นโค้ดเดียวกันที่เขียนด้วย Kotlin

val building64Bit = false

ใช้ is เป็นคำนำหน้าพร็อพเพอร์ตี้บูลีน

Groovy ใช้ตรรกะการหักพร็อพเพอร์ตี้ตามชื่อพร็อพเพอร์ตี้ สําหรับพร็อพเพอร์ตี้บูลีน foo เมธอดที่อนุมานอาจเป็น getFoo, setFoo หรือ isFoo ดังนั้นเมื่อแปลงเป็น Kotlin แล้ว คุณจะต้องเปลี่ยนชื่อพร็อพเพอร์ตี้เป็นเมธอดที่ดึงข้อมูลซึ่ง Kotlin ไม่รองรับ เช่น buildTypes องค์ประกอบบูลีน DSL คุณต้องใส่ is ไว้ข้างหน้า โค้ดนี้แสดงวิธีตั้งค่าพร็อพเพอร์ตี้บูลีนใน Groovy

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

ต่อไปนี้คือโค้ดเดียวกันใน Kotlin โปรดทราบว่าพร็อพเพอร์ตี้จะมี is นำหน้า

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

แปลงรายการและแผนที่

รายการและแผนที่ใน Groovy และ Kotlin จะกำหนดโดยใช้ไวยากรณ์ที่แตกต่างกัน Groovy ใช้ [] ส่วน Kotlin จะเรียกใช้เมธอดการสร้างคอลเล็กชันโดยใช้ listOf หรือ mapOf อย่างชัดเจน โปรดตรวจสอบว่าได้แทนที่ [] ด้วย listOf หรือ mapOf เมื่อย้ายข้อมูล

วิธีกำหนดรายการใน Groovy เทียบกับ Kotlin มีดังนี้

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

นี่เป็นโค้ดเดียวกันที่เขียนด้วย Kotlin

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

วิธีกำหนดแผนที่ใน Groovy เทียบกับ Kotlin มีดังนี้

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

นี่เป็นโค้ดเดียวกันที่เขียนด้วย Kotlin

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

กำหนดค่าประเภทบิวด์

ใน Kotlin DSL จะมีเฉพาะประเภทบิลด์แก้ไขข้อบกพร่องและรุ่นที่ใช้ได้โดยปริยาย ส่วนประเภทบิลด์ที่กำหนดเองอื่นๆ ทั้งหมดจะต้องสร้างด้วยตนเอง

ใน Groovy คุณสามารถใช้บิลด์ประเภทแก้ไขข้อบกพร่อง เวอร์ชัน และอื่นๆ บางประเภทได้โดยไม่ต้องสร้างก่อน ข้อมูลโค้ดต่อไปนี้แสดงการกําหนดค่าที่มีประเภทการสร้าง debug, release และ benchmark ใน Groovy

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

หากต้องการสร้างการกำหนดค่าที่เทียบเท่าใน Kotlin คุณต้องสร้างประเภทการสร้าง benchmark อย่างชัดเจน

buildTypes {
 debug {
   ...
 }

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

ย้ายข้อมูลจาก buildscript ไปยังบล็อกปลั๊กอิน

หากบิลด์ใช้บล็อก buildscript {} เพื่อเพิ่มปลั๊กอินลงในโปรเจ็กต์ คุณควรปรับโครงสร้างใหม่เพื่อใช้บล็อก plugins {} แทน บล็อก plugins {} ช่วยให้ใช้ปลั๊กอินได้ง่ายขึ้น และทำงานร่วมกับแคตตาล็อกเวอร์ชันได้ดี

นอกจากนี้ เมื่อคุณใช้บล็อก plugins {} ในไฟล์บิลด์ Android Studio จะรับรู้บริบทแม้ว่าการสร้างจะล้มเหลวก็ตาม บริบทนี้จะช่วยแก้ไขไฟล์ Kotlin DSL เนื่องจากช่วยให้ IDE ของ Studio ดำเนินการเติมโค้ดให้สมบูรณ์และแสดงคำแนะนำที่เป็นประโยชน์อื่นๆ ได้

ค้นหารหัสปลั๊กอิน

ขณะที่บล็อก buildscript {} จะเพิ่มปลั๊กอินลงในเส้นทางคลาสของบิลด์โดยใช้พิกัด Maven ของปลั๊กอิน เช่น com.android.tools.build:gradle:7.4.0 ส่วนบล็อก plugins {} จะใช้รหัสปลั๊กอินแทน

สําหรับปลั๊กอินส่วนใหญ่ รหัสปลั๊กอินคือสตริงที่ใช้เมื่อคุณใช้ปลั๊กอินโดยใช้ apply plugin ตัวอย่างเช่น รหัสปลั๊กอินต่อไปนี้เป็นส่วนหนึ่งของปลั๊กอิน Android Gradle

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

ดูรายการปลั๊กอินทั้งหมดได้ที่ที่เก็บ Maven ของ Google

คุณสามารถอ้างอิงปลั๊กอิน Kotlin โดยใช้รหัสปลั๊กอินได้หลายรหัส เราขอแนะนำให้ใช้รหัสปลั๊กอินที่มีเนมสเปซ และเปลี่ยนรูปแบบจากตัวย่อเป็นรหัสปลั๊กอินที่มีเนมสเปซตามตารางต่อไปนี้

รหัสปลั๊กอินแบบย่อ รหัสปลั๊กอินที่มีเนมสเปซ
kotlin org.jetbrains.kotlin.jvm
kotlin-android org.jetbrains.kotlin.android
kotlin-kapt org.jetbrains.kotlin.kapt
kotlin-parcelize org.jetbrains.kotlin.plugin.parcelize

นอกจากนี้ คุณยังค้นหาปลั๊กอินใน Gradle Plugin Portal, Maven Central Repository และ ที่เก็บ Maven ของ Google ได้ด้วย อ่านหัวข้อการพัฒนาปลั๊กอิน Gradle ที่กําหนดเองเพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีการทำงานของรหัสปลั๊กอิน

ทำการรีแฟกทอริง

เมื่อทราบรหัสของปลั๊กอินที่ใช้แล้ว ให้ทำตามขั้นตอนต่อไปนี้

  1. หากคุณยังมีที่เก็บสำหรับปลั๊กอินที่ประกาศไว้ในบล็อก buildscript {} ให้ย้ายไปที่ไฟล์ settings.gradle แทน

  2. เพิ่มปลั๊กอินลงในบล็อก plugins {} ในไฟล์ระดับบนสุด build.gradle คุณต้องระบุรหัสและเวอร์ชันของปลั๊กอินที่นี่ หากไม่จำเป็นต้องใช้ปลั๊กอินกับโปรเจ็กต์รูท ให้ใช้ apply false

  3. นำรายการ classpath ออกจากไฟล์ build.gradle.kts ระดับบนสุด

  4. ใช้ปลั๊กอินโดยเพิ่มลงในบล็อก plugins {} ในไฟล์ build.gradle ระดับโมดูล คุณเพียงต้องระบุรหัสของปลั๊กอินที่นี่เท่านั้น เนื่องจากระบบจะรับค่าเวอร์ชันมาจากโปรเจ็กต์รูท

  5. นําการเรียก apply plugin สําหรับปลั๊กอินออกจากไฟล์ build.gradle ระดับโมดูล

ตัวอย่างเช่น การตั้งค่านี้ใช้บล็อก 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")

การตั้งค่าที่เทียบเท่าโดยใช้บล็อก 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()
    }
}

แปลงบล็อกปลั๊กอิน

การใช้ปลั๊กอินจากบล็อก plugins {} นั้นคล้ายกันใน Groovy และ Kotlin โค้ดต่อไปนี้แสดงวิธีใช้ปลั๊กอินใน Groovy เมื่อคุณใช้แคตตาล็อกเวอร์ชัน

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

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

โค้ดต่อไปนี้แสดงวิธีทําแบบเดียวกันใน 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)
   ...
}

โค้ดต่อไปนี้แสดงวิธีใช้ปลั๊กอินใน Groovy เมื่อคุณไม่ได้ใช้แคตตาล็อกเวอร์ชัน

// 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'
   ...
}

โค้ดต่อไปนี้แสดงวิธีทําแบบเดียวกันใน 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")
   ...
}

ดูรายละเอียดเพิ่มเติมเกี่ยวกับบล็อก plugins {} ได้ที่การใช้ปลั๊กอินในเอกสารประกอบของ Gradle

เบ็ดเตล็ด

ดูตัวอย่างโค้ด Kotlin สำหรับฟังก์ชันการทำงานอื่นๆ ได้ที่หน้าเอกสารประกอบต่อไปนี้

ปัญหาที่ทราบ

ปัญหาที่ทราบในปัจจุบันคือความเร็วในการบิลด์อาจช้ากว่าเมื่อใช้ Kotlin เมื่อเทียบกับ Groovy

วิธีรายงานปัญหา

ดูวิธีการให้ข้อมูลที่จําเป็นสําหรับการจัดลําดับความสําคัญของปัญหาได้ที่หัวข้อรายละเอียดสําหรับเครื่องมือสร้างและข้อบกพร่อง Gradle จากนั้นรายงานข้อบกพร่องโดยใช้เครื่องมือติดตามปัญหาสาธารณะของ Google

แหล่งข้อมูลเพิ่มเติม

ดูตัวอย่างไฟล์บิลด์ Gradle ที่เขียนด้วย Kotlin ได้ที่แอปตัวอย่าง Now In Android ใน GitHub