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 validi 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 specifica, una classe base o una classe annotata, 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(); }Quando possibile, utilizza le annotazioni nel codice sorgente e poi scegli come target queste annotazioni direttamente nelle regole di conservazione. In questo modo viene creato un collegamento chiaro ed esplicito tra il codice e le regole che lo preservano, rendendo la configurazione più solida, più facile da comprendere e meno soggetta a interruzioni quando il codice cambia.
Ad esempio, il seguente snippet mostra come puoi conservare la classe MyClass, nonché altre classi annotate con
@com.example.DisplayComponent:// In the source code @com.example.DisplayComponent class MyClass { /* ... */ } // In the keep rules -keep @com.example.DisplayComponent class * {*;}Ti consigliamo di denominare le annotazioni in modo che forniscano un contesto significativo perché le parti di codice vengono conservate. Ad esempio, utilizza
@DisplayComponentper un'app in cui i componenti di visualizzazione richiedono che alcune parti vengano mantenute.Se possibile, la specifica del membro deve essere dichiarata e fare riferimento solo alle parti della classe che devono essere mantenute per il funzionamento dell'app. Ti consigliamo di non applicare una regola a un'intera classe definendo l'ambito dei membri 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 pacchetto facoltativo. In questo modo, i file DEX sono più piccoli perché il prefisso del pacchetto viene omesso nei nomi delle classi ricompilate.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, mantenere le regole effettive è fondamentale perché le modifiche future al codice potrebbero portare R8 a non conservare più questi elementi.
Se non riesci a rispettare queste linee guida, puoi isolare temporaneamente il codice che deve essere conservato in un pacchetto dedicato e applicare la regola di conservazione al pacchetto. Tuttavia, questa non è una soluzione a lungo termine. Per scoprire 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 della regola di conservazione offre molte opzioni, ma per ottenere vantaggi misurabili in termini di prestazioni sostenibili consigliamo di non utilizzare le seguenti:
- Non utilizzare regole di conservazione a livello di pacchetto, ad esempio
-keep class com.example.pkg.** { *; }a lungo termine. Possono essere utilizzati temporaneamente per risolvere i problemi durante la configurazione di R8. Per ulteriori informazioni, vedi Limitare l'ambito dell'ottimizzazione. In generale, fai attenzione ai caratteri jolly: assicurati di conservare solo il codice necessario. - 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 devono evitare la reflection, se possibile, e incorporare le regole di conservazione dei consumatori quando necessario.
- Evita di utilizzare l'operatore di inversione
!nelle regole di conservazione perché potresti applicare involontariamente una regola a quasi tutte le classi della tua applicazione.
Se non riesci a rispettare queste regole, potresti utilizzare molta reflection aperta e dovresti evitare la reflection o la libreria che la utilizza (vedi il case study di Gson).