העברת תצורת ה-build מ-Groovy ל-Kotlin

בגרסה 4.0 של הפלאגין של Android Gradle נוספה תמיכה בשימוש ב-Kotlin בתצורת ה-build של Gradle, כתחליף ל-Groovy – שפת התכנות שבאופן מסורתי משתמשים בה בקובצי התצורה של Gradle.

עדיף להשתמש ב-Kotlin על פני Groovy לכתיבת סקריפטים של Gradle, כי Kotlin קריא יותר ומציע בדיקה טובה יותר של משך הזמן לקימפול ותמיכה ב-IDE.

למרות ש-Kotlin מציעה כרגע שילוב טוב יותר בעורך הקוד של Android Studio בהשוואה ל-Groovy, גרסאות build שמשתמשות ב-Kotlin נוטות להיות איטיות יותר מגרסאות build שמשתמשות ב-Groovy, לכן כדאי להביא בחשבון את ביצועי ה-build כשמחליטים אם לעבור.

בדף הזה מוסבר איך להמיר את קובצי ה-build של Gradle באפליקציה ל-Android מ-Groovy ל-Kotlin. במסמכי התיעוד הרשמיים של Gradle יש מדריך מקיף יותר להעברת נתונים.

ציר הזמן

החל מ-Android Studio Giraffe, פרויקטים חדשים משתמשים ב-Kotlin DSL (build.gradle.kts) כברירת מחדל לתצורת build. הוא מציע חוויית עריכה טובה יותר מ-Groovy DSL‏ (build.gradle) עם הדגשת תחביר, השלמת קוד וניווט להצהרות. מידע נוסף זמין במאמר Gradle Kotlin DSL Primer.

מונחים נפוצים

‫Kotlin DSL: מתייחס בעיקר ל-פלאגין של Android Gradle Kotlin DSL או, לפעמים, ל-Gradle Kotlin DSL הבסיסי.

במדריך הזה להעברת נתונים (מיגרציה), המונחים Kotlin ו-Kotlin DSL משמשים לסירוגין. באופן דומה, המונחים "Groovy" ו-"Groovy DSL" משמשים לסירוגין.

מתן שמות לקובצי סקריפטים

השמות של סיומות קובצי הסקריפטים מבוססים על השפה שבה כתוב קובץ ה-build:

  • קובצי build של Gradle שכתובים ב-Groovy משתמשים בסיומת הקובץ .gradle.
  • קובצי build של Gradle שכתובים ב-Kotlin משתמשים בסיומת הקובץ .gradle.kts.

המרת התחביר

יש כמה הבדלים כלליים בתחביר בין Groovy ל-Kotlin, לכן צריך להחיל את השינויים האלה בכל הסקריפטים של ה-build.

הוספת סוגריים להפעלות של method

ב-Groovy אפשר להשמיט סוגריים בהפעלות של methods, אבל ב-Kotlin צריך להוסיף אותם. כדי להעביר את ההגדרות, צריך להוסיף סוגריים להפעלות ה-method האלה. הקוד הזה מראה איך להגדיר הגדרה ב-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() ב-project, ולא ב-project.rootDir. כדי לקבל את הערך של תיקיית השורש, צריך להקיף את הביטוי ${project.rootDir} בסוגריים מסולסלים:

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

    מידע נוסף זמין במאמר בנושא תבניות מחרוזת במסמכי התיעוד של Kotlin.

שינוי סיומות של קבצים

מוסיפים את הסיומת .kts לכל קובץ build כשמעבירים את התוכן שלו. לדוגמה, בוחרים קובץ build, כמו הקובץ settings.gradle. משנים את שם הקובץ ל-settings.gradle.kts וממירים את תוכן הקובץ ל-Kotlin. חשוב לוודא שהפרויקט עדיין עובר הידור אחרי ההעברה של כל קובץ build.

כדאי להתחיל בהעברת הקבצים הקטנים ביותר, לצבור ניסיון ואז להמשיך. בפרויקט יכול להיות שילוב של קובצי build ב-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")

הגדרת סוגי גרסאות build

ב-Kotlin DSL, רק סוגי ה-build לניפוי באגים וגרסת build להפצה זמינים באופן משתמע. צריך ליצור באופן ידני את כל שאר הסוגים של גרסאות build בהתאמה אישית.

ב-Groovy אפשר להשתמש בסוגי ה-build‏ debug,‏ release וסוגים מסוימים אחרים בלי ליצור אותם קודם. בקטע הקוד הבא מוצגת הגדרה עם סוגי ה-build‏ debug,‏ release ו-benchmark ב-Groovy.

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

כדי ליצור את ההגדרה המקבילה ב-Kotlin, צריך ליצור באופן מפורש את סוג ה-build‏ benchmark.

buildTypes {
 debug {
   ...
 }

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

מעבר מ-buildscript לבלוק plugins

אם ה-build שלכם משתמש בבלוק buildscript {} כדי להוסיף פלאגינים לפרויקט, צריך לארגן את הקוד מחדש כך שישתמש בבלוק plugins {} במקום זאת. הבלוק plugins {} מקל על החלת פלאגינים, והוא פועל היטב עם קטלוגים של גרסאות.

בנוסף, כשמשתמשים בבלוק plugins {} בקובצי ה-build, ‏Android Studio מודע להקשר גם אם ה-build נכשל. ההקשר הזה עוזר לתקן את קובצי ה-DSL של Kotlin, כי הוא מאפשר ל-Studio IDE להשלים את הקוד ולספק הצעות מועילות אחרות.

איך מוצאים את מזהי הפלאגינים

הבלוק buildscript {} מוסיף את הפלאגינים ל-classpath של ה-build באמצעות הקואורדינטות של 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 וב-Google Maven repository. במאמר Developing Custom Gradle Plugins מוסבר איך מזהי פלאגינים פועלים.

ביצוע ה-refactoring

אחרי שאתם יודעים מהם המזהים של הפלאגינים שבהם אתם משתמשים, אתם צריכים לבצע את השלבים הבאים:

  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 {}, קראו את המאמר Applying plugins במסמכי התיעוד של Gradle.

שונות

דוגמאות קוד ב-Kotlin לפונקציות אחרות מופיעות בדפי התיעוד הבאים:

בעיות מוכרות

בעיה ידועה היא שמהירות ה-build עשויה להיות איטית יותר ב-Kotlin מאשר ב-Groovy.

איך מדווחים על בעיות

במאמר פרטים על באגים בכלי build וב-Gradle מוסבר איך לספק את המידע שאנחנו צריכים כדי לטפל בבעיה. אחר כך, מדווחים על באג באמצעות הכלי הציבורי של Google למעקב אחר בעיות.

משאבים נוספים

ב-GitHub יש אפליקציה לדוגמה של Now In Android, שכוללת דוגמה פעילה של קובצי build של Gradle שכתובים ב-Kotlin.