Adotta le ottimizzazioni in modo incrementale

Per impostazione predefinita, R8 esegue molte ottimizzazioni per migliorare le prestazioni e le dimensioni, ma le ottimizzazioni potrebbero non funzionare immediatamente per la tua app. Se attivi R8 (o la modalità completa) per la prima volta in un'app di grandi dimensioni, prova ad adottare le ottimizzazioni in modo incrementale: disattiva temporaneamente l'offuscamento e attiva R8 per parti di codice alla volta, anziché per tutto il codice dell'app. Ti consigliamo di adottare questo approccio incrementale durante lo sviluppo locale, ma puoi utilizzarlo anche durante i test di QA interni o addirittura in produzione come implementazione graduale. I passaggi esatti che esegui dipendono dalle tempistiche che vuoi rispettare e dalla sicurezza della copertura dei test pre-release.

Limitare le ottimizzazioni

R8 esegue molti tipi di ottimizzazioni, tra cui rimozione di codice, riscrittura di codice e rimozione di risorse. Ecco alcune descrizioni generali dei tipi di ottimizzazione:

  • Riduzione del codice (o tree shaking): rimuove il codice a cui non viene fatto riferimento
  • Offuscamento (o minimizzazione degli identificatori): abbrevia i nomi di classi e metodi
  • Ottimizzazione: riscrivere il codice, ad esempio l'inserimento in linea

Per ridurre le possibilità di errori, puoi iniziare attivando solo alcune di queste ottimizzazioni.

Attiva solo lo scuotimento dell'albero

La riduzione del codice, nota anche come tree shaking, rimuove il codice che sembra non fare riferimento a nulla. Ti consigliamo di iniziare solo con l'analisi dell'albero, poiché è la più semplice.

Per attivare solo l'oscillazione dell'albero, aggiungi quanto segue al file proguard-rules.pro per disattivare gli altri tipi di ottimizzazioni. La disattivazione dell'offuscamento è fondamentale perché semplifica notevolmente la lettura delle tracce dello stack.

-dontobfuscate // Use temporarily to turn off identifier minification
-dontoptimize // Use temporarily to turn off optimization

Alla fine, non è consigliabile utilizzare questa configurazione, poiché limita drasticamente la capacità di R8 di ottimizzare il codice, ma è un ottimo punto di partenza per adottare R8 per la prima volta in una base di codice di grandi dimensioni con problemi da risolvere.

Usare la modalità compatibilità

Per impostazione predefinita, R8 viene eseguito in modalità completa. La modalità completa offre un miglioramento significativo delle prestazioni e consente di risparmiare spazio, ma puoi disattivarla temporaneamente e utilizzare la modalità compatibilità quando attivi la minimizzazione per la prima volta.

Per utilizzare la modalità compatibilità, utilizza la seguente impostazione nel file gradle.properties:

android.enableR8.fullMode = false // Use temporarily to disable full mode

Attivare le altre ottimizzazioni

Una volta verificato che lo shaking dell'albero funziona per la tua app, puoi rimuovere le impostazioni precedenti per riattivare l'offuscamento, l'ottimizzazione e la modalità completa R8. Tieni presente che l'oscuramento può rendere più difficile il debug, motivo per cui consigliamo di risolvere prima i problemi di tree shaking.

Per ulteriori informazioni sulla deoffuscazione delle analisi dello stack, consulta Recuperare l'analisi dello stack originale.

Limitare l'ambito dell'ottimizzazione

Una build completamente ottimizzata ottimizza tutto il codice di ogni libreria e pacchetto, quindi è normale riscontrare problemi con R8 la prima volta che lo attivi. Se riscontri un problema con l'ottimizzazione in una parte dell'app, non disattivare completamente R8, altrimenti perderai i vantaggi in tutte le altre parti. Disattiva temporaneamente R8 solo nelle parti dell'app che causano problemi.

Utilizzare le regole di conservazione a livello di pacchetto

Ti consigliamo di utilizzare le regole keep a livello di pacchetto per disattivare temporaneamente R8 in alcune parti della tua app. Dovresti sempre tornare a risolvere questi problemi di ottimizzazione in un secondo momento. In genere, si tratta di una soluzione temporanea per aggirare le aree problematiche.

Ad esempio, se parte della tua app utilizza Gson in modo intensivo e causa problemi di ottimizzazione, la soluzione ideale è aggiungere altre regole di mantenimento mirate o passare a una soluzione di codegen. Tuttavia, per sbloccare l'ottimizzazione del resto dell'app, puoi inserire il codice che definisce i tipi Gson in un sottopacchetto dedicato e aggiungere una regola come questa al file proguard-rules.pro:

-keep class com.myapp.json.** { *; }

Se una libreria che utilizzi ha la riflessione nei componenti interni, puoi aggiungere una regola di mantenimento per l'intera libreria in modo simile. Dovrai esaminare il codice o il file JAR/AAR della libreria per trovare il pacchetto appropriato da conservare. Anche in questo caso, non è consigliabile mantenere questa impostazione a lungo termine, ma può sbloccare l'ottimizzazione del resto dell'app:

-keep class com.somelibrary.** { *; }

Rimuovere le regole di conservazione a livello di pacchetto

Una volta che l'app funziona correttamente con le regole keep a livello di pacchetto, devi tornare indietro e aggiungere regole keep mirate o rimuovere l'utilizzo o la libreria di riflessione che richiede la regola keep.

Ad esempio, in AndroidX è estremamente comune mantenere tutte le regole che estendono una determinata classe per conservare solo le classi pertinenti. In genere, la riflessione deve avere come target solo classi o metodi che estendono determinate classi astratte, implementano determinate interfacce o classi con un'annotazione di runtime specifica. Ognuno di questi è un modo supportato per definire le regole di conservazione in modo da non doverle avere per l'intero pacchetto nell'app finale completamente ottimizzata.