Adopter les optimisations de manière incrémentielle

Par défaut, R8 effectue de nombreuses optimisations pour améliorer les performances et la taille, mais il est possible que les optimisations ne fonctionnent pas immédiatement pour votre application. Si vous activez R8 (ou le mode complet) dans une grande application pour la première fois, essayez d'adopter des optimisations de manière incrémentielle: désactivez temporairement l'obscurcissement et activez R8 pour des parties de code à la fois, plutôt que pour tout le code de votre application. Nous vous recommandons d'adopter cette approche incrémentielle lors du développement local, mais vous pouvez également l'utiliser lors des tests de contrôle qualité internes ou même en production en tant que déploiement progressif. Les étapes exactes que vous suivez dépendent du calendrier souhaité et de votre confiance dans la couverture des tests en version préliminaire.

Limiter les optimisations

R8 effectue de nombreux types d'optimisations, y compris la suppression de code, la réécriture de code et la suppression de ressources. Voici quelques descriptions générales des types d'optimisation:

  • Minification de code (ou tree shaking): supprime le code non référencé
  • Obscurcissement (ou minification de l'identifiant): raccourcit les noms des classes et des méthodes
  • Optimisation: réécrit le code, par exemple en l'inlining

Pour réduire le risque d'erreurs, vous pouvez commencer par n'activer que certaines de ces optimisations.

Activer uniquement le balayage de l'arborescence

La minification de code, également appelée "tree shaking", supprime le code qui semble ne pas être référencé. Nous vous recommandons de commencer par le balayage d'arbre, car il est le plus simple.

Pour activer le ramassage d'arbre uniquement, ajoutez le code suivant à votre fichier proguard-rules.pro pour désactiver les autres types d'optimisations. Désactiver l'obscurcissement est essentiel, car il rend les traces de pile beaucoup plus faciles à lire.

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

Au final, vous ne voudrez pas expédier cette configuration, car elle limite considérablement la capacité de R8 à optimiser le code. Toutefois, elle constitue un excellent point de départ lorsque vous adoptez R8 pour la première fois dans un grand codebase présentant des problèmes à résoudre.

Utiliser le mode compatibilité

Par défaut, R8 s'exécute en mode complet. Le mode complet offre des performances et des économies de taille nettement améliorées, mais vous pouvez le désactiver temporairement et utiliser le mode compatibilité à la place lorsque vous activez la minification pour la première fois.

Pour utiliser le mode compatibilité, utilisez le paramètre suivant dans votre fichier gradle.properties:

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

Activer le reste des optimisations

Une fois que vous avez vérifié que le balayage d'arbre fonctionne pour votre application, vous pouvez supprimer les paramètres précédents pour réactiver l'obscurcissement, l'optimisation et le mode complet R8. Notez que l'obscurcissement peut rendre le débogage plus difficile. C'est pourquoi nous vous recommandons de commencer par résoudre les problèmes de suppression d'arbre.

Pour en savoir plus sur le désobscurcissement des traces de pile, consultez la section "Récupérer la trace de pile d'origine".

Limiter le champ d'application de l'optimisation

Un build entièrement optimisé optimise tout le code de chaque bibliothèque et de chaque package. Il est donc courant de rencontrer des problèmes avec R8 lorsque vous l'activez pour la première fois. Si vous constatez un problème d'optimisation dans une partie de l'application, ne désactivez pas complètement R8, sinon vous perdrez les avantages partout ailleurs. Désactivez plutôt temporairement R8 uniquement dans les parties de votre application qui posent problème.

Utiliser des règles de conservation au niveau du package

Nous vous recommandons d'utiliser des règles de conservation à l'échelle du package pour désactiver temporairement R8 dans certaines parties de votre application. Vous devez toujours revenir pour résoudre ces problèmes d'optimisation plus tard. Il s'agit généralement d'une solution provisoire pour contourner les problèmes.

Par exemple, si une partie de votre application utilise beaucoup Gson et pose des problèmes d'optimisation, la solution idéale consiste à ajouter d'autres règles de conservation ciblées ou à passer à une solution de codegen. Toutefois, pour débloquer l'optimisation du reste de l'application, vous pouvez placer le code définissant vos types Gson dans un sous-package dédié et ajouter une règle comme celle-ci à votre fichier proguard-rules.pro:

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

Si une bibliothèque que vous utilisez comporte une réflexion dans des composants internes, vous pouvez également ajouter une règle de conservation pour l'ensemble de la bibliothèque. Vous devrez inspecter le code ou le fichier JAR/AAR de la bibliothèque pour trouver le package approprié à conserver. Encore une fois, nous vous déconseillons de maintenir cette approche à long terme, mais elle peut débloquer l'optimisation du reste de l'application:

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

Supprimer les règles de conservation au niveau du package

Une fois que votre application fonctionne correctement avec les règles de conservation au niveau du package, vous devez revenir en arrière et ajouter des règles de conservation ciblées ou supprimer l'utilisation ou la bibliothèque de réflexion qui nécessite la règle de conservation.

Par exemple, il est extrêmement courant dans AndroidX de conserver toutes les règles qui étendent une classe donnée afin de ne conserver que les classes pertinentes. En général, la réflexion ne doit cibler que des classes ou des méthodes qui étendent certaines classes abstraites, implémentent certaines interfaces ou sont associées à une annotation d'exécution spécifique. Chacune de ces méthodes est acceptée pour définir des règles de conservation afin que vous n'ayez pas besoin de règles de conservation à l'échelle du package dans votre application finale entièrement optimisée.