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.

Lebih memilih codegen daripada refleksi

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

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 untuk pengoptimalan aplikasi karena menggunakan codegen, bukan refleksi. Saat menggunakan refleksi, mereka memberikan aturan penyimpanan minimal untuk menyimpan hanya kode yang diperlukan.
  • Library serialisasi sering menggunakan refleksi untuk menghindari kode boilerplate saat membuat instance atau melakukan serialisasi objek. Daripada menggunakan pendekatan berbasis refleksi (seperti Gson untuk JSON), cari library yang menggunakan codegen untuk menghindari masalah ini, misalnya dengan menggunakan Kotlin Serialization.
  • Library yang menyertakan aturan keep di seluruh paket harus dihindari jika memungkinkan. Aturan keep di seluruh paket dapat membantu mengatasi error, tetapi aturan keep yang luas pada akhirnya harus disempurnakan untuk menyimpan hanya kode yang diperlukan. Untuk mengetahui informasi selengkapnya, lihat Menerapkan pengoptimalan secara inkremental.
  • Library tidak boleh mengharuskan Anda menyalin dan menempelkan aturan penyimpanan dari dokumentasi ke dalam file di project Anda, terutama aturan penyimpanan di seluruh paket. Aturan ini akan menjadi beban pemeliharaan bagi developer aplikasi dalam jangka panjang, serta sulit dioptimalkan dan diubah dari waktu ke waktu.

Mengaktifkan pengoptimalan setelah menambahkan pustaka 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 penyimpanan. Jika library tidak kompatibel dengan pengoptimalan, laporkan bug pada library tersebut.

Aturan bersifat kumulatif

Perhatikan bahwa aturan penyimpanan bersifat kumulatif. 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.

Memeriksa penggunaan refleksi (lanjutan)

Anda mungkin dapat mengetahui apakah library menggunakan refleksi dari pemeriksaan kodenya. Jika library menggunakan refleksi, periksa apakah library tersebut menyediakan aturan keep 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 penyimpanan yang buruk (lanjutan)

Anda harus menghindari library dengan aturan keep yang mempertahankan kode yang seharusnya dihapus. Namun, jika Anda 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: Mengapa Gson rusak karena pengoptimalan

Gson adalah library serialisasi yang sering menyebabkan masalah pada pengoptimalan aplikasi karena sangat banyak menggunakan refleksi. Cuplikan kode berikut menunjukkan cara penggunaan Gson biasanya, yang dapat dengan mudah menyebabkan error saat runtime. Perhatikan bahwa saat Anda menggunakan Gson untuk mendapatkan daftar objek Pengguna, Anda tidak memanggil konstruktor atau meneruskan pabrik ke fungsi fromJson(). Membuat atau menggunakan class yang ditentukan aplikasi tanpa salah satu dari berikut ini adalah tanda bahwa library mungkin menggunakan refleksi terbuka:

  • Class aplikasi yang menerapkan 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 di-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 apakah library tersebut tidak akan mengganggu pengoptimalan aplikasi, dan jika ya, hindari penggunaannya.

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