Seguire le best practice

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 corretti 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 si crea 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 per il motivo per cui le parti di codice vengono conservate. Ad esempio, utilizza @DisplayComponent per un'app in cui alcuni componenti di visualizzazione richiedono che alcune parti vengano conservate.

  • Quando 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 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 ricompilate.

  • Mantieni le regole di conservazione per tutti gli elementi a cui si accede tramite la funzionalità di mirroring. Anche se questi elementi vengono conservati da R8 senza regole di conservazione esplicite, il mantenimento delle regole effettive è fondamentale perché le modifiche future al codice potrebbero portare R8 a non conservare più questi elementi.

  • Se possibile, utilizza -assumenosideeffects o -convertchecknotnull per ottimizzare i controlli null perché ciò può ridurre significativamente le dimensioni del DEX della tua app. Per saperne di più, vedi Tipi di regole aggiuntivi.

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 ti 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 saperne di più, consulta 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).