Untuk mengaktifkan pengoptimalan aplikasi, Anda harus menggunakan library yang kompatibel dengan pengoptimalan Android. Jika library tidak dikonfigurasi untuk pengoptimalan Android—misalnya, jika menggunakan refleksi tanpa memaketkan aturan keep terkait—library tersebut mungkin tidak cocok untuk aplikasi Android. Halaman ini menjelaskan alasan beberapa library lebih cocok untuk pengoptimalan aplikasi dan memberikan tips umum untuk membantu Anda memilih.
Tips umum saat memilih library
Gunakan tips ini untuk membantu memastikan library Anda kompatibel dengan pengoptimalan aplikasi.
Memilih codegen daripada refleksi
Pilih library yang menggunakan pembuatan kode (codegen) dan bukan refleksi. Dengan codegen, pengoptimal dapat menentukan kode mana yang sebenarnya digunakan saat runtime dan kode mana yang dapat dihapus. Mungkin sulit untuk mengetahui apakah library menggunakan codegen atau refleksi, tetapi ada beberapa tanda—lihat tips untuk mendapatkan bantuan.
Untuk mengetahui informasi selengkapnya tentang codegen versus refleksi, lihat Pengoptimalan untuk penulis library.
Memeriksa penggunaan refleksi (lanjutan)
Anda dapat mengetahui apakah library menggunakan refleksi dengan memeriksa kodenya. Jika library menggunakan refleksi, pastikan library tersebut menyediakan aturan keep terkait. Library kemungkinan menggunakan refleksi jika melakukan hal berikut:
- Menggunakan class atau metode dari paket
kotlin.reflectataujava.lang.reflect. - Menggunakan fungsi
Class.forNameatauclassLoader.getClass. - Membaca anotasi saat runtime, misalnya jika menyimpan nilai anotasi
menggunakan
val value = myClass.getAnnotation()atauval value = myMethod.getAnnotation(), lalu melakukan sesuatu denganvalue. Memanggil metode menggunakan nama metode sebagai string, seperti dalam contoh berikut:
// Calls the private `processData` API with reflection myObject.javaClass.getMethod("processData", DataType::class.java) ?.invoke(myObject, data)
Memeriksa masalah pengoptimalan
Saat mempertimbangkan library baru, lihat issue tracker library dan diskusi online untuk memeriksa apakah ada masalah terkait minifikasi atau mengonfigurasi pengoptimalan aplikasi. Jika ada, Anda harus mencoba mencari alternatif untuk library tersebut. Perhatikan hal berikut:
- Library AndroidX dan library seperti Hilt berfungsi dengan baik dengan pengoptimalan aplikasi karena sebagian besar menggunakan codegen, bukan refleksi. Saat menggunakan refleksi, library tersebut menyediakan aturan keep minimal untuk menyimpan kode yang diperlukan saja.
- Library serialisasi sering menggunakan refleksi untuk menghindari kode boilerplate saat membuat instance atau melakukan serialisasi objek. Daripada pendekatan berbasis refleksi (seperti Gson untuk JSON), cari library yang menggunakan codegen untuk menghindari masalah ini, misalnya dengan menggunakan Serialisasi Kotlin atau Moshi dengan codegen.
- Jika memungkinkan, hindari library yang menyertakan aturan keep di seluruh paket. Aturan keep di seluruh paket dapat membantu mengatasi error, tetapi aturan keep yang luas pada akhirnya harus disempurnakan agar hanya menyimpan kode yang diperlukan. Untuk mengetahui informasi selengkapnya, lihat Menerapkan pengoptimalan secara bertahap.
- Sebelum memublikasikan aplikasi yang menggunakan library pihak ketiga, gunakan R8 Configuration Analyzer untuk mengaudit aturan keep yang disediakan. Dengan meninjau laporan, Anda dapat memverifikasi apakah aturan keep library terlalu luas, sehingga mencegah R8 melakukan pengoptimalan penting pada codebase Anda. Pemeriksaan ini memastikan bahwa library yang Anda pilih selaras dengan sasaran performa aplikasi dan tidak menyebabkan bloat konfigurasi yang tidak perlu.
- Library tidak boleh mengharuskan Anda menyalin dan menempel aturan keep dari dokumentasi ke file dalam project, terutama aturan keep di seluruh paket. Aturan ini akan menjadi beban pemeliharaan bagi developer aplikasi dalam jangka panjang, dan sulit dioptimalkan serta diubah dari waktu ke waktu.
Mengaktifkan pengoptimalan setelah menambahkan library baru
Saat Anda menambahkan library baru, aktifkan pengoptimalan setelahnya dan periksa apakah ada error. Jika ada error, cari alternatif untuk library tersebut atau tulis aturan keep. Jika library tidak kompatibel dengan pengoptimalan, ajukan bug untuk library tersebut.
Memfilter aturan keep yang buruk (lanjutan)
Aturan keep bersifat aditif. Artinya, aturan tertentu yang disertakan dependensi library tidak dapat dihapus dan dapat memengaruhi kompilasi bagian lain dari aplikasi Anda. Misalnya, jika library menyertakan aturan untuk menonaktifkan pengoptimalan kode, aturan tersebut akan menonaktifkan pengoptimalan untuk seluruh project Anda.
Anda harus menghindari library dengan aturan keep yang mempertahankan kode yang seharusnya dihapus. Namun, jika Anda harus menggunakannya, Anda dapat memfilter aturan tersebut seperti yang ditunjukkan dalam kode berikut:
// If you're using AGP 8.4 and higher
buildTypes {
release {
optimization.keepRules {
it.ignoreFrom("com.somelibrary:somelibrary")
}
}
}
// If you're using AGP 7.3-8.3
buildTypes {
release {
optimization.keepRules {
it.ignoreExternalDependencies("com.somelibrary:somelibrary")
}
}
}
Studi kasus: Mengapa Gson tidak berfungsi dengan pengoptimalan
Gson adalah library serialisasi yang sering menyebabkan masalah dengan pengoptimalan aplikasi karena sangat menggunakan refleksi. Cuplikan kode berikut menunjukkan cara Gson biasanya digunakan, yang dapat menyebabkan error saat runtime. Perhatikan bahwa saat Anda menggunakan Gson untuk mendapatkan daftar objek Pengguna, Anda tidak memanggil konstruktor atau meneruskan factory ke fungsi fromJson(). Membuat atau menggunakan class yang ditentukan aplikasi tanpa salah satu hal berikut adalah tanda bahwa library mungkin menggunakan refleksi terbuka:
- Class aplikasi yang mengimplementasikan library, atau antarmuka atau class standar
- Plugin pembuatan kode seperti KSP
class User(val name: String)
class UserList(val users: List<User>)
// This code runs in debug mode, but crashes when optimizations are enabled
Gson().fromJson("""[{"name":"myname"}]""", User::class.java).toString()
Untuk memahami cara kerja R8 pada Gson, lihat aturan konsumen Gson. Saat R8
menganalisis kode ini dan tidak melihat UserList atau User yang dibuat instance
di mana pun, R8 dapat mengganti nama kolom, atau menghapus konstruktor yang tampaknya tidak
digunakan, sehingga menyebabkan aplikasi Anda error. Jika Anda menggunakan library lain dengan cara yang serupa, Anda harus memeriksa bahwa library tersebut tidak akan mengganggu pengoptimalan aplikasi, dan jika mengganggu, hindari library tersebut.
Menggunakan @SerializedName dengan versi Gson yang lebih baru
Untuk menentukan model data Anda dengan cara yang kompatibel dengan aturan konsumen Gson, beri anotasi pada kolom Anda dengan @SerializedName, seperti yang ditunjukkan dalam cuplikan berikut:
import com.google.gson.annotations.SerializedName
class User(@SerializedName("name") val name: String)
class UserList(@SerializedName("users") val users: List<User>)
Dengan menggunakan anotasi @SerializedName, Anda mengizinkan R8 mencocokkan class model
dengan aturan keep yang di-bundle dalam Gson versi 2.11.0 dan yang lebih baru.
R8 secara otomatis mempertahankan kolom yang diberi anotasi dan konstruktor yang diperlukan, sehingga Anda dapat mengandalkan aturan yang di-bundle library tanpa harus mempertahankan konfigurasi ProGuard manual dalam project Anda.
Perhatikan bahwa Room, Hilt, dan Moshi dengan codegen membuat jenis yang ditentukan aplikasi, tetapi menggunakan codegen untuk menghindari kebutuhan akan refleksi.