Mengikuti praktik terbaik

Saat bekerja dengan aturan penyimpanan, penting untuk mencapai jumlah spesifisitas yang tepat untuk memastikan Anda mendapatkan manfaat sekaligus mempertahankan perilaku aplikasi Anda. Lihat bagian berikut untuk mempelajari pola yang baik serta hal-hal yang harus dihindari dalam aturan penyimpanan.

Pola yang baik dalam aturan penyimpanan

Aturan penyimpanan yang ditentukan dengan baik bersifat spesifik mungkin:

  • Untuk spesifikasi class, selalu tentukan class, class dasar, atau class beranotasi tertentu jika memungkinkan, seperti yang ditunjukkan dalam contoh berikut:

    -keepclassmembers class com.example.MyClass {
      void someSpecificMethod();
    }
    
    -keepclassmembers ** extends com.example.MyBaseClass {
      void someSpecificMethod();
    }
    
    -keepclassmembers @com.example.MyAnnotation class ** {
      void someSpecificMethod();
    }
    
  • Jika memungkinkan, gunakan anotasi pada kode sumber Anda (seperti anotasi @Keep ), lalu targetkan anotasi tersebut secara langsung dalam aturan keep Anda. Hal ini akan membuat link yang jelas dan eksplisit antara kode Anda dan aturan yang melindunginya, sehingga konfigurasi Anda menjadi lebih tangguh, lebih mudah dipahami, dan tidak terlalu rentan terhadap kerusakan saat kode berubah.

    Misalnya, library seperti androidx.annotation menggunakan pola ini:

    // In your source code
    @Keep
    class MyDataClass { /* ... */ }
    
    // In your R8 rules
    -keep @androidx.annotation.DisplayComponent class * {*;}
    

    Sebaiknya beri nama anotasi Anda sehingga memberikan konteks yang bermakna tentang alasan bagian kode dipertahankan. Misalnya, gunakan @DisplayComponent untuk aplikasi yang komponen tampilannya memerlukan beberapa bagian untuk dipertahankan.

  • Jika memungkinkan, spesifikasi anggota harus dideklarasikan, dan hanya merujuk pada bagian class yang harus dipertahankan agar aplikasi berfungsi. Sebaiknya jangan menerapkan aturan ke seluruh class dengan menentukan cakupan anggota opsional sebagai { *; } kecuali jika benar-benar diperlukan.

    -keepclassmembers com.example.MyClass {
      void someSpecificMethod();
      void @com.example.MyAnnotation *;
    }
    
  • Jika Anda menggunakan opsi global repackageclasses, hindari penetapan nama paket opsional. Hal ini menghasilkan file DEX yang lebih kecil karena awalan paket dihilangkan dalam nama class yang dikemas ulang.

Jika tidak dapat mematuhi pedoman ini, Anda dapat mengisolasi kode yang perlu dipertahankan dalam paket khusus untuk sementara dan menerapkan aturan keep ke paket tersebut. Namun, hal ini bukan solusi jangka panjang. Untuk mempelajari lebih lanjut, lihat Menerapkan pengoptimalan secara bertahap. Untuk menggunakan aturan penyimpanan untuk paket, tentukan aturan penyimpanan seperti yang ditunjukkan dalam contoh berikut:

-keepclassmembers class com.example.pkg.** { *; }

Hal yang perlu dihindari

Sintaksis aturan penyimpanan memiliki banyak opsi, tetapi untuk manfaat performa berkelanjutan yang terukur, sebaiknya jangan gunakan opsi berikut:

  • Hindari penggunaan operator inversi ! dalam aturan penyimpanan karena Anda dapat secara tidak sengaja menerapkan aturan ke hampir setiap class dalam aplikasi Anda.
  • Jangan gunakan aturan penyimpanan di seluruh paket seperti -keep class com.example.pkg.** { *; } dalam jangka panjang. Opsi ini dapat digunakan untuk sementara waktu untuk mengatasi masalah saat mengonfigurasi R8. Untuk mengetahui informasi selengkapnya, lihat Membatasi cakupan pengoptimalan. Secara umum, berhati-hatilah dengan karakter pengganti—pastikan Anda hanya menyimpan kode yang Anda butuhkan.

Jika Anda tidak dapat mengikuti aturan ini, Anda mungkin menggunakan banyak refleksi berbentuk terbuka, dan sebaiknya hindari refleksi atau hindari penggunaan library dengan refleksi (lihat studi kasus Gson).