Quando lavori con le regole di conservazione, è importante raggiungere il giusto livello di specificità per assicurarti di ottenere vantaggi mantenendo il comportamento della tua app. Consulta le sezioni seguenti per scoprire i pattern consigliati e le cose da evitare nelle regole di conservazione.
Pattern consigliati nelle regole di conservazione
Le regole di conservazione ben definite sono il più specifiche possibile e rispettano i seguenti pattern:
Per la specifica della classe, specifica sempre una classe, una classe base o una classe con annotazioni specifica, se possibile, come mostrato negli esempi seguenti:
-keepclassmembers class com.example.MyClass { void someSpecificMethod(); }-keepclassmembers ** extends com.example.MyBaseClass { void someSpecificMethod(); }-keepclassmembers @com.example.MyAnnotation class ** { void someSpecificMethod(); }Se possibile, utilizza le annotazioni nel codice sorgente e poi applica il targeting a queste annotazioni direttamente nelle regole di conservazione. In questo modo, crei un collegamento chiaro ed esplicito tra il codice e le regole che lo conservano, rendendo la configurazione più solida, più facile da comprendere e meno soggetta a interruzioni quando il codice cambia.
Ad esempio, lo snippet seguente mostra come puoi conservare la classe MyClass, nonché altre classi con l'annotazione
@com.example.DisplayComponent:// In the source code @com.example.DisplayComponent class MyClass { /* ... */ } // In the keep rules -keep @com.example.DisplayComponent class * {*;}Ti consigliamo di assegnare alle annotazioni nomi che forniscano un contesto significativo del motivo per cui le parti del codice vengono conservate. Ad esempio, utilizza
@DisplayComponentper un'app in cui i componenti di visualizzazione richiedono la conservazione di alcune parti.Se possibile, la specifica del membro deve essere dichiarata e deve fare riferimento solo alle parti della classe che devono essere conservate per il funzionamento dell'app. Ti consigliamo di non applicare una regola a un'intera classe definendo l'ambito del membro facoltativo come
{ *; }a meno che non sia strettamente necessario.-keepclassmembers com.example.MyClass { void someSpecificMethod(); void @com.example.MyAnnotation *; }Se utilizzi l'opzione globale
repackageclasses, evita di specificare il nome del pacchetto facoltativo. In questo modo, i file DEX sono più piccoli perché il prefisso del pacchetto viene omesso nei nomi delle classi riconfezionate.Mantieni le regole di conservazione per tutti gli elementi a cui si accede tramite reflection. Anche se questi elementi vengono conservati da R8 senza regole di conservazione esplicite, è fondamentale mantenere le regole effettive perché le modifiche future del codice potrebbero portare R8 a non conservare più questi elementi.
Per la reflection nel tuo codice, puoi utilizzare Jetpack Keep per generare regole di conservazione più facili da gestire. Ogni annotazione si trova nel codice che esegue la reflection, quindi quando modifichi il codice, aggiorni o rimuovi l'annotazione nello stesso punto. In questo modo, le regole non conservano il codice su cui la tua app non esegue più la reflection. Lint segnala anche le chiamate reflective che non sono annotate.
Se possibile, utilizza
-assumenosideeffectso-convertchecknotnullper ottimizzare i controlli null perché in questo modo puoi ridurre significativamente le dimensioni del DEX della tua app. Per saperne di più, consulta Tipi di regole aggiuntivi.
Se non riesci a rispettare queste linee guida, puoi isolare temporaneamente il codice da conservare in un pacchetto dedicato e applicare la regola di conservazione al pacchetto. Tuttavia, questa non è una soluzione a lungo termine. Per saperne di più, consulta Adottare le ottimizzazioni in modo incrementale. Per utilizzare una regola di conservazione per un pacchetto, definisci una regola di conservazione come mostrato nell'esempio seguente:
-keepclassmembers class com.example.pkg.** { *; }
Cose da evitare
La sintassi delle regole di conservazione offre molte opzioni, ma per ottenere vantaggi misurabili e sostenibili in termini di rendimento, ti consigliamo di non utilizzare le seguenti:
- Non utilizzare a lungo termine regole di conservazione a livello di pacchetto come
-keep class com.example.pkg.** { *; }. Possono essere utilizzate temporaneamente per risolvere i problemi durante la configurazione di R8. Per saperne di più, consulta Limitare l'ambito di ottimizzazione. In generale, fai attenzione ai caratteri jolly: assicurati di conservare solo il codice di cui hai bisogno. - Se possibile, evita le librerie che ti suggeriscono di copiare e incollare le regole di conservazione quando le utilizzi, in particolare le regole di conservazione a livello di pacchetto. Le librerie progettate per funzionare bene su Android dovrebbero evitare la reflection, se possibile, e incorporare le regole di conservazione dei consumer quando necessario.
- Evita di utilizzare l'operatore di inversione
!nelle regole di conservazione perché potresti applicare involontariamente una regola a quasi tutte le classi dell'applicazione.
Se non riesci a seguire queste regole, potresti utilizzare molta reflection open-ended e dovresti evitare la reflection o la libreria che la utilizza (vedi il case study di Gson).