Pengoptimalan untuk penulis library

Sebagai penulis library, Anda harus memastikan bahwa developer aplikasi dapat dengan mudah memasukkan library Anda ke dalam aplikasi mereka sekaligus mempertahankan pengalaman pengguna akhir yang berkualitas tinggi. Anda harus memastikan bahwa library Anda kompatibel dengan pengoptimalan Android tanpa penyiapan tambahan—atau mendokumentasikan bahwa library mungkin tidak sesuai untuk digunakan di Android.

Dokumentasi ini ditujukan untuk developer library yang dipublikasikan, tetapi mungkin juga berguna bagi developer modul library internal dalam aplikasi besar yang dimodularisasi.

Jika Anda adalah developer aplikasi dan ingin mempelajari cara mengoptimalkan aplikasi Android, lihat Mengaktifkan pengoptimalan aplikasi. Untuk mempelajari library yang sesuai untuk digunakan, lihat Memilih library dengan bijak.

Menggunakan codegen daripada refleksi

Jika memungkinkan, gunakan pembuatan kode (codegen) daripada refleksi. Codegen dan refleksi adalah pendekatan umum untuk menghindari kode boilerplate saat memprogram, tetapi codegen lebih kompatibel dengan pengoptimal aplikasi seperti R8:

  • Dengan codegen, kode dianalisis dan diubah selama proses build. Karena tidak ada modifikasi besar setelah waktu kompilasi, pengoptimal mengetahui kode yang pada akhirnya diperlukan dan kode yang dapat dihapus dengan aman.
  • Dengan refleksi, kode dianalisis dan dimanipulasi saat runtime. Karena kode tidak benar-benar selesai hingga dieksekusi, pengoptimal tidak tahu kode apa saja yang dapat dihapus dengan aman. Tindakan ini kemungkinan akan menghapus kode yang digunakan secara dinamis melalui refleksi selama runtime, yang menyebabkan error aplikasi bagi pengguna.

Banyak library modern menggunakan codegen, bukan refleksi. Lihat KSP untuk titik entri umum, yang digunakan oleh Room, Dagger2, dan banyak lagi.

Saat refleksi diizinkan

Jika harus menggunakan refleksi, Anda hanya boleh memantulkan ke salah satu hal berikut:

  • Jenis yang ditargetkan secara spesifik (penerapkan antarmuka atau subclass tertentu)
  • Kode yang menggunakan anotasi runtime tertentu

Menggunakan refleksi dengan cara ini akan membatasi biaya runtime, dan memungkinkan penulisan aturan penyimpanan konsumen yang ditargetkan.

Bentuk refleksi spesifik dan tertarget ini adalah pola yang dapat Anda lihat di framework Android (misalnya saat meng-inflate aktivitas, tampilan, dan drawable) dan library AndroidX (misalnya saat membuat WorkManager ListenableWorkers, atau RoomDatabases). Sebaliknya, refleksi terbuka Gson tidak sesuai untuk digunakan di aplikasi Android.

Menulis aturan simpan konsumen

Library harus memaketkan aturan keep "konsumen", yang menggunakan format yang sama dengan aturan keep aplikasi. Aturan ini dipaketkan ke dalam artefak library (AAR atau JAR) dan digunakan secara otomatis selama pengoptimalan aplikasi Android saat library digunakan.

Library AAR

Untuk menambahkan aturan konsumen untuk library AAR, gunakan opsi consumerProguardFiles dalam skrip build modul library Android. Untuk informasi selengkapnya, lihat panduan kami tentang membuat modul library.

Kotlin

android {
    defaultConfig {
        consumerProguardFiles("consumer-proguard-rules.pro")
    }
    ...
}

Groovy

android {
    defaultConfig {
        consumerProguardFiles 'consumer-proguard-rules.pro'
    }
    ...
}

Library JAR

Untuk memaketkan aturan dengan library Kotlin/Java yang dikirim sebagai JAR, tempatkan file aturan Anda di direktori META-INF/proguard/ JAR akhir, dengan nama file apa pun. Misalnya, jika kode Anda berada di <libraryroot>/src/main/kotlin, tempatkan file aturan konsumen di <libraryroot>/src/main/resources/META-INF/proguard/consumer-proguard-rules.pro dan aturan akan dipaketkan di lokasi yang benar dalam JAR output Anda.

Pastikan JAR final memaketkan aturan dengan benar dengan memeriksa apakah aturan tersebut ada di direktori META-INF/proguard.

Mendukung berbagai penyingkat (lanjutan)

Anda dapat menyesuaikan aturan ke penyingkat tertentu yang ditargetkan (R8 atau ProGuard), serta versi penyingkat tertentu. Hal ini memungkinkan library Anda berfungsi secara optimal dalam project yang menggunakan versi penyingkat baru, sekaligus memungkinkan aturan yang ada terus digunakan dalam project dengan versi penyingkat yang lebih lama.

Untuk menentukan aturan penyingkatan yang ditargetkan, Anda harus menyertakannya di lokasi tertentu di dalam library AAR atau JAR, seperti yang dijelaskan di bawah.

In an AAR library:
    consumer-proguard-rules.pro (legacy location)
    classes.jar
    └── META-INF
        └── com.android.tools (targeted shrink rules location)
            ├── r8-from-<X>-upto-<Y>/<R8-rules-file>
            └── proguard-from-<X>-upto-<Y>/<ProGuard-rules-file>

In a JAR library:
    META-INF
    ├── proguard/<ProGuard-rules-file> (legacy location)
    └── com.android.tools (targeted shrink rules location)
        ├── r8-from-<X>-upto-<Y>/<R8-rules-file>
        └── proguard-from-<X>-upto-<Y>/<ProGuard-rules-file>

Artinya, aturan penyingkatan yang ditargetkan disimpan di direktori META-INF/com.android.tools JAR atau di direktori META-INF/com.android.tools di dalam classes.jar AAR.

Di direktori tersebut, dapat ada beberapa direktori dengan nama dalam bentuk r8-from-<X>-upto-<Y> atau proguard-from-<X>-upto-<Y> untuk menunjukkan versi shrinker yang aturannya ditulis di dalam direktori. Perhatikan bahwa bagian -from-<X> dan -upto-<Y> bersifat opsional, versi <Y> eksklusif, dan rentang versi harus berkelanjutan.

Misalnya, r8-upto-8.0.0, r8-from-8.0.0-upto-8.2.0, dan r8-from-8.2.0 membentuk kumpulan aturan penyingkatan yang ditargetkan yang valid. Aturan di bawah direktori r8-from-8.0.0-upto-8.2.0 akan digunakan oleh R8 dari versi 8.0.0 hingga tetapi tidak termasuk versi 8.2.0.

Dengan informasi tersebut, plugin Android Gradle akan memilih aturan dari direktori R8 yang cocok. Jika library tidak menentukan aturan penyingkatan yang ditargetkan, plugin Android Gradle akan memilih aturan dari lokasi lama (proguard.txt untuk AAR atau META-INF/proguard/<ProGuard-rules-file> untuk JAR).