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:
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 (ad esempio un'annotazione
@Keep
) 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, librerie come
androidx.annotation
utilizzano questo pattern:// In your source code @Keep class MyDataClass { /* ... */ } // In your R8 rules -keep @androidx.annotation.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
@DisplayComponent
per un'app in cui alcuni componenti di visualizzazione richiedono che alcune parti vengano mantenute.Ove 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.
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:
- 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. - 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 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).