Mengikuti praktik terbaik

Saat bekerja dengan aturan penyimpanan, Anda harus mencapai tingkat 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 sespesifik mungkin dan mematuhi pola berikut:

  • 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, 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 mempertahankannya, sehingga membuat konfigurasi Anda lebih tangguh, lebih mudah dipahami, dan tidak terlalu rentan terhadap kerusakan saat kode berubah.

    Misalnya, cuplikan berikut menunjukkan cara mempertahankan class MyClass, serta class lain yang diberi anotasi dengan @com.example.DisplayComponent:

    // In the source code
    @com.example.DisplayComponent
    class MyClass { /* ... */ }
    
    // In the keep rules
    -keep @com.example.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.

  • Pertahankan aturan penyimpanan untuk semua item yang diakses oleh refleksi. Meskipun item tersebut dipertahankan oleh R8 tanpa aturan keep eksplisit, mempertahankan aturan sebenarnya sangat penting karena perubahan kode di masa mendatang dapat menyebabkan R8 tidak lagi mempertahankan item ini.

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:

  • 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 memungkinkan, hindari library yang menyarankan Anda menyalin dan menempelkan aturan penyimpanan saat Anda menggunakannya, terutama aturan penyimpanan di seluruh paket. Library yang didesain agar berfungsi dengan baik di Android harus menghindari refleksi jika memungkinkan dan menyematkan aturan penyimpanan konsumen jika diperlukan.
  • Hindari penggunaan operator inversi ! dalam aturan penyimpanan karena Anda dapat secara tidak sengaja menerapkan aturan ke hampir setiap class dalam aplikasi Anda.

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).