ใช้ฟีเจอร์และ API สำหรับภาษาของ Java 8

ปลั๊กอิน Android Gradle 3.0.0 ขึ้นไปรองรับฟีเจอร์ภาษา Java 7 ทั้งหมดและฟีเจอร์ภาษา Java 8 บางรายการที่ขึ้นอยู่กับเวอร์ชันแพลตฟอร์ม เมื่อสร้างแอปโดยใช้ Android Gradle Plugin 4.0.0 ขึ้นไป คุณจะใช้ API ภาษา Java 8 บางรายการได้โดยไม่ต้องกำหนดระดับ API ขั้นต่ำสำหรับแอป

หน้านี้จะอธิบายฟีเจอร์ภาษา Java 8 ที่คุณใช้ได้ วิธีกำหนดค่าโปรเจ็กต์อย่างเหมาะสมเพื่อใช้ฟีเจอร์ดังกล่าว และปัญหาที่ทราบซึ่งคุณอาจพบ ดูภาพรวมของฟีเจอร์ภาษา Java 8 ได้ในวิดีโอต่อไปนี้

ปลั๊กอิน Android Gradle มีการสนับสนุนในตัวสำหรับการใช้ฟีเจอร์ภาษา Java 8 บางรายการและไลบรารีของบุคคลที่สามที่ใช้ฟีเจอร์ดังกล่าว เครื่องมือทํางานเริ่มต้นจะใช้ฟีเจอร์ภาษาใหม่โดยทําการเปลี่ยนรูปแบบไบต์โค้ดที่เรียกว่า 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 Plugin 3.0.0 ขึ้นไป ปลั๊กอินจะไม่รองรับฟีเจอร์ภาษา Java 8 บางรายการ ฟีเจอร์ภาษาต่อไปนี้พร้อมใช้งานในทุกระดับ API

ฟีเจอร์ภาษาของ Java 8 หมายเหตุ
นิพจน์ Lambda Android ไม่รองรับการแปลงค่านิพจน์ Lambda เป็นรูปแบบที่เป็นระเบียบ
ข้อมูลอ้างอิงวิธีการ  
คำอธิบายประกอบประเภท ข้อมูลคําอธิบายประกอบประเภทจะใช้ได้เมื่อคอมไพล์เท่านั้น ไม่ใช่เมื่อรันไทม์ แพลตฟอร์มรองรับ TYPE ใน API ระดับ 24 และต่ำกว่า แต่ไม่รองรับ ElementType.TYPE_USE หรือ ElementType.TYPE_PARAMETER
เมธอดอินเทอร์เฟซเริ่มต้นและแบบคงที่  
คำอธิบายประกอบที่ซ้ำกัน  

นอกจากฟีเจอร์ภาษา Java 8 เหล่านี้แล้ว ปลั๊กอิน Android Gradle เวอร์ชัน 3.0.0 ขึ้นไปยังรองรับ try-with-resources ในระดับ API ของ Android ทั้งหมดด้วย

Desugar ไม่รองรับ 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 ขึ้นไปมีฟีเจอร์การนำ Sugar ออกในปลั๊กอิน Android Gradle 3.0.0 ขึ้นไป และไม่ทำให้คลาสและ API เพิ่มเติม (เช่น java.util.stream.*) พร้อมใช้งานใน Android เวอร์ชันเก่า การรองรับการแปลง Java API บางส่วนเป็นรูปแบบปกติมีให้ใช้งานจากปลั๊กอิน Android Gradle 4.0.0 ขึ้นไปตามที่อธิบายไว้ในส่วนต่อไปนี้

รองรับการแปลง API ของ Java 8 ขึ้นไปให้เป็นรูปแบบทั่วไป (Android Gradle Plugin 4.0.0 ขึ้นไป)

หากคุณสร้างแอปโดยใช้ Android Gradle Plugin 4.0.0 ขึ้นไป ปลั๊กอินจะขยายการรองรับการใช้ API ภาษา Java 8 หลายรายการโดยไม่กำหนดระดับ API ขั้นต่ำสำหรับแอปของคุณ เมื่อใช้ Android Gradle Plugin 7.4.0 ขึ้นไป คุณจะใช้ API ภาษา Java 11 หลายรายการได้ด้วยไลบรารี Desugared 2.0.0 ขึ้นไป

การรองรับแพลตฟอร์มเวอร์ชันเก่าเพิ่มเติมนี้เป็นไปได้เนื่องจากปลั๊กอิน 4.0.0 ขึ้นไปขยายการทำงานของเครื่องมือถอด Sugar ออกเพื่อถอด Sugar ออกจาก 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 ขึ้นไป ระบบจะรองรับ Java 11 API เพิ่มเติม เช่น ชุดย่อยของแพ็กเกจ java.nio.file

ดูรายการ API ที่รองรับทั้งหมดได้ที่ API ของ Java 8 ขึ้นไปที่ใช้ได้ผ่านการถอด Sugar และ API ของ Java 11 ขึ้นไปที่ใช้ได้ผ่านการถอด Sugar

เพื่อรองรับ API ภาษาเหล่านี้ ปลั๊กอินจะคอมไพล์ไฟล์ DEX แยกต่างหากซึ่งมีการใช้งาน API ที่ขาดหายไปและรวมไว้ในแอปของคุณ กระบวนการถอด Sugar จะเขียนโค้ดของแอปใหม่เพื่อใช้ไลบรารีนี้แทนที่รันไทม์ ซอร์สโค้ดที่คอมไพล์เป็นไฟล์ 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 ของไลบรารีหรือโมดูลด้วยในกรณีต่อไปนี้

  • การทดสอบที่มีเครื่องมือวัดผลของโมดูลไลบรารีจะใช้ Language API เหล่านี้ (โดยตรงหรือผ่านโมดูลไลบรารีหรือ Dependency ของโมดูล) การดำเนินการนี้เพื่อให้มี API ที่ขาดหายไปสําหรับ APK ทดสอบที่มีเครื่องมือวัด

  • คุณต้องการเรียกใช้ Lint ในโมดูลไลบรารีแยกต่างหาก วิธีนี้ช่วยให้ Lint จดจำการใช้งานที่ถูกต้องของ Language API และหลีกเลี่ยงการรายงานคำเตือนที่ไม่ถูกต้อง

นอกจากนี้ โปรดทราบว่าการกรอง Sugar ออกจาก API สามารถใช้ร่วมกับการลดขนาดได้ แต่จะใช้ได้ก็ต่อเมื่อใช้เครื่องมือลดขนาด R8 เท่านั้น

เวอร์ชัน

ตารางต่อไปนี้แสดงเวอร์ชันของไลบรารี 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

ดูรายละเอียดเกี่ยวกับเวอร์ชันของไลบรารี Java 8 ขึ้นไปได้ที่ไฟล์ CHANGELOG.md ในที่เก็บข้อมูล desugar_jdk_libs GitHub