Memilih library dengan bijak

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.

Memilih codegen daripada refleksi

Umumnya, Anda harus memilih library yang menggunakan pembuatan kode (codegen), bukan refleksi. Dengan codegen, pengoptimal dapat lebih mudah menentukan kode yang sebenarnya digunakan saat runtime dan kode yang dapat dihapus. 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.

Tips umum saat memilih library

Gunakan tips ini untuk membantu memastikan bahwa library Anda kompatibel dengan pengoptimalan aplikasi.

Memeriksa masalah pengoptimalan

Saat mempertimbangkan library baru, lihat pelacak masalah dan diskusi online library untuk memeriksa apakah ada masalah terkait minifikasi atau mengonfigurasi pengoptimalan aplikasi. Jika ada, Anda harus mencoba mencari alternatif untuk library tersebut. Ingat hal berikut:

  • Library AndroidX dan library seperti Hilt berfungsi dengan baik dengan optimasi aplikasi karena menggunakan codegen, bukan refleksi. Saat menggunakan refleksi, mereka memberikan aturan penyimpanan minimum untuk hanya menyimpan kode yang diperlukan.
  • 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.
  • Library yang menyertakan aturan keep seluruh paket harus dihindari jika memungkinkan. Aturan keep seluruh paket dapat membantu menyelesaikan error, tetapi aturan keep yang luas pada akhirnya harus ditingkatkan kualitasnya agar hanya menyimpan kode yang diperlukan. Untuk mengetahui informasi selengkapnya, lihat Mengimplementasikan pengoptimalan secara bertahap.

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, laporkan bug dengan library tersebut.

Aturan bersifat kumulatif

Perhatikan bahwa aturan simpan bersifat aditif. Artinya, aturan tertentu yang disertakan dependensi library tidak dapat dihapus dan dapat memengaruhi kompilasi bagian lain aplikasi Anda. Misalnya, jika library menyertakan aturan untuk menonaktifkan pengoptimalan kode, aturan tersebut akan menonaktifkan pengoptimalan untuk seluruh project Anda.

Memeriksa penggunaan refleksi (lanjutan)

Anda mungkin dapat mengetahui apakah library menggunakan refleksi dari pemeriksaan kodenya. Jika library menggunakan refleksi, pastikan library tersebut menyediakan aturan keep yang terkait. Library mungkin menggunakan refleksi jika melakukan hal berikut:

  • Menggunakan class atau metode dari paket kotlin.reflect atau java.lang.reflect
  • Menggunakan fungsi Class.forName atau classLoader.getClass
  • Membaca anotasi saat runtime, misalnya jika menyimpan nilai anotasi menggunakan val value = myClass.getAnnotation() atau val value = myMethod.getAnnotation(), lalu melakukan sesuatu dengan value
  • Memanggil metode menggunakan nama metode sebagai string, misalnya:

    // Calls the private `processData` API with reflection
    myObject.javaClass.getMethod("processData", DataType::class.java)
    ?.invoke(myObject, data)
    

Memfilter aturan simpan yang buruk (lanjutan)

Anda harus menghindari library dengan aturan keep yang mempertahankan kode yang benar-benar harus dihapus. Namun, jika harus menggunakannya, Anda dapat memfilter aturan 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: Alasan Gson mengalami error dengan pengoptimalan

Gson adalah library serialisasi yang sering menyebabkan masalah pada pengoptimalan aplikasi karena banyak menggunakan refleksi. Cuplikan kode berikut menunjukkan cara Gson biasanya digunakan, yang dapat dengan mudah menyebabkan error saat runtime. Perhatikan bahwa saat 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 dari 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()

Saat R8 menganalisis kode ini dan tidak melihat UserList atau User yang dibuat instance-nya 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 apakah library tersebut tidak akan mengganggu pengoptimalan aplikasi, dan jika ya, hindari library tersebut.

Perhatikan bahwa Room dan Hilt keduanya membuat jenis yang ditentukan aplikasi, tetapi menggunakan codegen untuk menghindari kebutuhan akan refleksi.