שימוש בתכונות שפה ובממשקי API של Java 8

הפלאגין של Android Gradle מגרסה 3.0.0 ואילך תומך בכל תכונות השפה של Java 7 ובקבוצת משנה של תכונות השפה של Java 8, שמשתנות בהתאם לגרסה של הפלטפורמה. כשאתם מפתחים את האפליקציה באמצעות הפלאגין של Android Gradle מגרסה 4.0.0 ואילך, אתם יכולים להשתמש בחלק מממשקי ה-API של שפת Java 8 בלי שתצטרכו להגדיר רמת API מינימלית לאפליקציה.

בדף הזה מתוארות תכונות השפה של Java 8 שבהן אפשר להשתמש, איך להגדיר את הפרויקט בצורה נכונה כדי להשתמש בהן ובעיות ידועות שעשויות לצוץ. בסרטון הבא מופיעה סקירה כללית של תכונות השפה של Java 8.

הפלאגין של Android ל-Gradle מספק תמיכה מובנית בשימוש בתכונות מסוימות של שפת Java 8 ובספריות של צד שלישי שמשתמשות בהן. כלי הפיתוח שמוגדרים כברירת מחדל מטמיעים את תכונות השפה החדשות על ידי ביצוע טרנספורמציות של קוד באייטה (bytecode), שנקראות desugar, כחלק מהקמפלקציה של D8/R8 של קובצי הכיתה לקוד DEX, כפי שמוצג באיור 1.

תמיכה בתכונות של שפת Java 8 באמצעות טרנספורמציות של קוד בייט של 'desugar'
איור 1. תמיכה בתכונות של שפת Java 8 באמצעות desugar טרנספורמציות של קוד בייט.

תמיכה בתכונות של שפת Java 8 (פלאגין Android Gradle מגרסה 3.0.0 ואילך)

כדי להתחיל להשתמש בתכונות נתמכות של שפת Java 8:

  1. מעדכנים את הפלאגין של Android Gradle לגרסה 3.0.0 ואילך.
  2. לכל מודול שמשתמש בתכונות השפה של Java 8 (בקוד המקור שלו או דרך יחסי תלות), מעדכנים את הקובץ build.gradle או build.gradle.kts של המודול כפי שמתואר בהמשך:

Kotlin

android {
    ...
    // Configure only for each module that uses Java 8
    // language features (either in its source code or
    // through dependencies).
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
    // For Kotlin projects
    kotlinOptions {
        jvmTarget = "1.8"
    }
}

Groovy

android {
    ...
    // Configure only for each module that uses Java 8
    // language features (either in its source code or
    // through dependencies).
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    // For Kotlin projects
    kotlinOptions {
        jvmTarget = "1.8"
    }
}

כשמפתחים אפליקציה באמצעות הפלאגין של Android Gradle מגרסה 3.0.0 ואילך, הפלאגין לא תומך בכל תכונות השפה של Java 8. התכונות הבאות של שפות תכנות זמינות בכל רמת API:

מאפיין שפה של Java 8 הערות
ביטויים מסוג Lambda Android לא תומך בסריאליזציה של ביטויי lambda.
חומר עזר בנושא שיטות  
הערות לגבי סוגים המידע על הערות הסוג זמין רק בזמן הידור, ולא בזמן הריצה. הפלטפורמה תומכת ב-TYPE ברמת API 24 ומטה, אבל לא ב-ElementType.TYPE_USE או ב-ElementType.TYPE_PARAMETER.
שיטות ממשק סטטיות ושל ברירת מחדל  
הערות חוזרות  

בנוסף לתכונות האלה בשפת Java 8, בגרסאות 3.0.0 ואילך של הפלאגין של Android Gradle הורחבה התמיכה ב- try-with-resources לכל רמות ה-API של Android.

הכלי להסרת סוכר לא תומך ב-MethodHandle.invoke או ב-MethodHandle.invokeExact. אם קוד המקור או אחת מהתלות במודולים משתמשים באחת מהשיטות האלה, צריך לציין minSdkVersion 26 ואילך. אחרת, תופיע הודעת השגיאה הבאה:

Dex: Error converting bytecode to dex:
Cause: signature-polymorphic method called without --min-sdk-version >= 26

במקרים מסוימים, יכול להיות שהמודול לא משתמש בשיטות invoke או invokeExact גם אם הן כלולות בספרייה שתלויה בו. כדי להמשיך להשתמש בספרייה הזו עם minSdkVersion 25 ואילך, צריך להפעיל כיווץ קוד כדי להסיר שיטות שלא בשימוש. אם הבעיה נמשכת, כדאי להשתמש בספרייה חלופית שלא משתמשת בשיטות שלא נתמכות.

שפת Java מגרסה 8 ואילך כוללת הסרה של סוכר (desugaring) בפלאגין Android Gradle בגרסה 3.0.0 ואילך, ולא מאפשרת להשתמש בעוד כיתות ו-API (כמו java.util.stream.*) בגרסאות Android ישנות יותר. תמיכה בביטול סוכר חלקי של Java API זמינה ב-Android Gradle Plugin בגרסה 4.0.0 ואילך, כפי שמתואר בקטע הבא.

תמיכה בביטול הסוכרה של ממשקי API מגרסה 8 ואילך של Java (Android Gradle Plugin מגרסה 4.0.0 ואילך)

אם אתם מפתחים את האפליקציה באמצעות הפלאגין של Android Gradle מגרסה 4.0.0 ואילך, הפלאגין מרחיב את התמיכה בשימוש במספר ממשקי API של שפת Java 8 בלי שתצטרכו להגדיר רמת API מינימלית לאפליקציה. עם הפלאגין של Android Gradle מגרסה 7.4.0 ואילך, מספר ממשקי API של שפת Java 11 זמינים גם עם ספרייה 2.0.0 ואילך ללא סוכר.

התמיכה הנוספת בגרסאות ישנות יותר של הפלטפורמה אפשרית כי התוסף מגרסה 4.0.0 ואילך מרחיב את מנוע הסרת הסוכר כך שיוכל גם להסיר סוכר מממשקי API בשפת Java. אפשר לכלול ממשקי API רגילים של שפה שהיו זמינים רק בגרסאות האחרונות של Android (כמו java.util.streams) באפליקציות שתומכות בגרסאות ישנות יותר של Android.

קבוצת ממשקי ה-API הבאה נתמכת כשיוצרים אפליקציה באמצעות הפלאגין של Android Gradle מגרסה 4.0.0 ואילך:

  • שידורים רציפים (java.util.stream)
  • קבוצת משנה של java.time
  • java.util.function
  • התוספות האחרונות ל-java.util.{Map,Collection,Comparator}
  • אופציונלים (java.util.Optional,‏ java.util.OptionalInt ו-java.util.OptionalDouble) וכמה כיתות חדשות
  • כמה תוספות ל-java.util.concurrent.atomic (שיטות חדשות ב-AtomicInteger, ב-AtomicLong וב-AtomicReference)
  • ConcurrentHashMap (עם תיקוני באגים ל-Android 5.0)

עם הפלאגין של Android Gradle בגרסה 7.4.0 ואילך, יש תמיכה בממשקי API נוספים של Java 11, כמו קבוצת משנה של החבילה java.nio.file.

בקישור הבא תוכלו למצוא רשימה מלאה של ממשקי ה-API הנתמכים: ממשקי API של Java מגרסה 8 ואילך שזמינים באמצעות הסרת סוכר. בקישור הבא תוכלו למצוא רשימה מלאה של ממשקי ה-API של Java מגרסה 11 ואילך שזמינים באמצעות הסרת סוכר: ממשקי API של Java מגרסה 11 ואילך שזמינים באמצעות הסרת סוכר.

כדי לתמוך ב-API של השפות האלה, הפלאגין יוצר קובץ DEX נפרד שמכיל הטמעה של ממשקי ה-API החסרים, ומשלב אותו באפליקציה. תהליך הסרת הסוכר מכתיב מחדש את קוד האפליקציה כך שבזמן הריצה היא תשתמש בספרייה הזו במקום ב-API. קוד המקור שעבר הידור לקובץ DEX נפרד זמין במאגר GitHub‏ desugar_jdk_libs.

כדי להפעיל תמיכה בממשקי ה-API האלה בשפות בכל גרסה של פלטפורמת Android:

  1. מעדכנים את הפלאגין של Android Gradle לגרסה 4.0.0 (או גרסה מתקדמת יותר).
  2. מוסיפים את הפרטים הבאים לקובץ build.gradle או build.gradle.kts של מודול האפליקציה:

Kotlin

android {
    defaultConfig {
        // Required when setting minSdkVersion to 20 or lower
        multiDexEnabled = true
    }

    compileOptions {
        // Flag to enable support for the new language APIs

        // For AGP 4.1+
        isCoreLibraryDesugaringEnabled = true
        // For AGP 4.0
        // coreLibraryDesugaringEnabled = true

        // Sets Java compatibility to Java 8
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
}

dependencies {
    // For AGP 7.4+
    coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.3")
    // For AGP 7.3
    // coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:1.2.3")
    // For AGP 4.0 to 7.2
    // coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:1.1.9")
}

Groovy

android {
    defaultConfig {
        // Required when setting minSdkVersion to 20 or lower
        multiDexEnabled true
    }

    compileOptions {
        // Flag to enable support for the new language APIs
        coreLibraryDesugaringEnabled true
        // Sets Java compatibility to Java 8
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    // For AGP 7.4+
    coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3'
    // For AGP 7.3
    // coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.2.3'
    // For AGP 4.0 to 7.2
    // coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.9'
}

הערה: יכול להיות שתצטרכו לכלול את קטע הקוד הקודם גם בקובץ build.gradle או build.gradle.kts של מודול הספרייה אם:

  • הבדיקות של מודול הספרייה שמתווספות אליהן מודדים משתמשות בממשקי ה-API של השפות האלה (באופן ישיר או דרך מודול הספרייה או יחסי התלות שלו). כך תוכלו להשתמש בממשקי ה-API החסרים בחבילת ה-APK לבדיקה עם הכלי למדידת ביצועים.

  • אתם רוצים להריץ את ה-lint על מודול הספרייה בנפרד. המטרה היא לעזור ל-lint לזהות שימושים חוקיים ב-API של השפה, וכך למנוע דיווח על אזהרות שווא.

חשוב גם לזכור שאפשר לשלב הסרת סוכר מ-API עם צמצום, אבל רק כשמשתמשים ב-R8 shrinker.

גרסאות

בטבלה הבאה מפורטות הגרסאות של ספריית ה-API של Java 8 ואילך וגרסה המינימלית של הפלאגין של Android Gradle שתומכת בכל גרסה:

גרסה הגרסה המינימלית של הפלאגין של Android Gradle
1.1.9 4.0.0
1.2.3 7.3.0
2.0.3 7.4.0-alpha10

פרטים על הגרסאות של ספריית ה-API ל-Java מגרסה 8 ואילך זמינים בקובץ CHANGELOG.md במאגר GitHub‏ desugar_jdk_libs.