Plus ils sont longs, plus les temps de compilation ralentissent le processus de développement. Cette page propose quelques techniques contribuant à résoudre les goulots d'étranglement liés à ce problème.
Voici les principales étapes à suivre pour améliorer la vitesse de compilation de votre application :
- Optimisez votre configuration de compilation en prenant quelques habitudes qui auront un impact positif immédiat sur la plupart des projets Android Studio.
- Effectuez le profilage de votre build afin d'identifier et d'analyser certains goulots d'étranglement qui peuvent être propres à votre projet ou à votre poste de travail.
Lorsque vous développez votre application, dans la mesure du possible, vous devez effectuer le déploiement sur un appareil exécutant Android version 7.0 (niveau d'API 24) ou ultérieure. Les versions plus récentes de la plate-forme Android disposent de meilleurs mécanismes de transmission des mises à jour de votre application, tels qu'Android Runtime (ART) et la prise en charge native de plusieurs fichiers DEX.
Remarque : Après votre première compilation propre, vous remarquerez peut-être que les compilations suivantes (qu'elles soient propres ou incrémentielles) sont beaucoup plus rapides (même sans utiliser les optimisations décrites sur cette page). En effet, le daemon Gradle a une période "d'échauffement" qui lui permet ensuite d'améliorer ses performances, comme c'est le cas avec d'autres processus JVM.
Optimiser votre configuration de compilation
Suivez ces conseils pour accélérer la compilation de votre projet Android Studio.
S'assurer que vos outils restent à jour
Les outils Android bénéficient d'optimisations de compilation et de nouvelles fonctionnalités à presque chaque mise à jour. Certains conseils figurant sur cette page supposent que vous utilisez la dernière version. Pour profiter des dernières optimisations, les outils suivants doivent être à jour :
Utiliser KSP au lieu de Kapt
L'outil de traitement des annotations Kotlin (Kapt) est beaucoup plus lent que Kotlin. Processeur de symboles (KSP). Si vous écrivez une source Kotlin annotée et que vous utilisez des outils traite les annotations (telles que Room). qui prend en charge KSP, vous devez migrer vers KSP.
Éviter de compiler des ressources inutiles
Évitez de compiler et d'inclure des ressources que vous ne testez pas (par exemple, les ressources d'autres langues ou d'autres densités d'écran). À la place, spécifiez une seule langue et une seule densité d'écran pour votre type de développement, comme illustré dans l'exemple suivant :
Groovy
android { ... productFlavors { dev { ... // The following configuration limits the "dev" flavor to using // English stringresources and xxhdpi screen-density resources. resourceConfigurations "en", "xxhdpi" } ... } }
Kotlin
android { ... productFlavors { create("dev") { ... // The following configuration limits the "dev" flavor to using // English stringresources and xxhdpi screen-density resources. resourceConfigurations("en", "xxhdpi") } ... } }
Testez l'intégration du portail du plug-in Gradle en dernier
Sous Android, tous les plug-ins se trouvent dans les dépôts google()
et mavenCentral()
. Cependant, votre build peut avoir recours à des plug-ins tiers résolus à l'aide du service gradlePluginPortal()
.
Pour les recherches, Gradle ouvre les dépôts dans l'ordre où ils sont déclarés. Par conséquent, les performances de compilation sont améliorées si les dépôts les plus hauts dans la liste contiennent la plupart des plug-ins. Il est donc judicieux d'essayer de mettre l'entrée gradlePluginPortal()
en dernier dans le bloc de dépôts de votre fichier settings.gradle
. Dans la plupart des cas, cela réduit considérablement le nombre de recherches redondantes de plug-ins et améliore la vitesse de compilation.
Pour en savoir plus sur la façon dont Gradle accède à plusieurs dépôts, consultez la section Déclarer plusieurs dépôts dans la documentation Gradle.
Utiliser des valeurs de configuration de compilation statiques avec votre version de débogage
Utilisez toujours des valeurs statiques pour les propriétés incluses dans le fichier manifeste ou dans les fichiers de ressources correspondant au type de version de débogage.
L'utilisation de codes de version dynamiques, de noms de versions, de ressources ou de toute autre logique de compilation qui modifie le fichier manifeste nécessite une compilation complète de l'application chaque fois que vous souhaitez apporter une modification, même si celle-ci ne nécessite qu'un remplacement rapide. Si votre configuration de compilation nécessite des propriétés dynamiques de ce type, isolez-les dans vos variantes de compilation et conservez les valeurs statiques pour vos versions de débogage, comme illustré dans l'exemple suivant :
... // Use a filter to apply onVariants() to a subset of the variants. onVariants(selector().withBuildType("release")) { variant -> // Because an app module can have multiple outputs when using multi-APK, versionCode // is only available on the variant output. // Gather the output when we are in single mode and there is no multi-APK. val mainOutput = variant.outputs.single { it.outputType == OutputType.SINGLE } // Create the version code generating task. val versionCodeTask = project.tasks.register("computeVersionCodeFor${variant.name}", VersionCodeTask::class.java) { it.outputFile.set(project.layout.buildDirectory.file("versionCode${variant.name}.txt")) } // Wire the version code from the task output. // map will create a lazy Provider that: // 1. Runs just before the consumer(s), ensuring that the producer (VersionCodeTask) has run // and therefore the file is created. // 2. Contains task dependency information so that the consumer(s) run after the producer. mainOutput.versionCode.set(versionCodeTask.flatMap { it.outputFile.map { it.asFile.readText().toInt() } }) } ... abstract class VersionCodeTask : DefaultTask() { @get:OutputFile abstract val outputFile: RegularFileProperty @TaskAction fun action() { outputFile.get().asFile.writeText("1.1.1") } }
Consultez la recette setVersionsFromTask sur GitHub pour découvrir comment définir un code de version dynamique dans un projet.
Utiliser des versions de dépendance statiques
Lorsque vous déclarez des dépendances dans vos fichiers build.gradle
, évitez d'utiliser des numéros de version dynamiques (ceux qui se terminent par un signe "plus", tels que 'com.android.tools.build:gradle:2.+'
). L'utilisation de numéros de version dynamiques peut entraîner des mises à jour de version inattendues, des difficultés pour résoudre les différences de version et des compilations plus lentes, car Gradle recherche des mises à jour.
Utilisez plutôt des numéros de version statiques.
Créer des modules de bibliothèque
Dans votre application, recherchez du code que vous pouvez convertir en module de bibliothèque Android. De cette manière, la modularisation de votre code permet au système de compilation de ne s'intéresser qu'aux modules que vous modifiez et de mettre en cache ces résultats pour les compilations futures. Cette technique permet également de gagner en efficacité lorsque vous exécutez plusieurs projets en parallèle (lorsque vous activez cette optimisation).
Créer des tâches pour une logique de compilation personnalisée
Une fois que vous avez créé un profil de compilation, s'il apparaît qu'une partie relativement longue du temps de compilation est consacrée à la phase de **configuration des projets**, examinez vos scripts build.gradle
et recherchez du code que vous pouvez inclure dans une tâche Gradle personnalisée. En déplaçant une partie de la logique de compilation dans une tâche, vous vous assurez que celle-ci ne s'exécute que lorsque cela est nécessaire, que les résultats peuvent être mis en cache pour les compilations suivantes et que cette logique peut être exécutée en parallèle si vous activez l'exécution de plusieurs projets en parallèle. Pour en savoir plus sur les tâches pour la logique de compilation personnalisée, consultez la documentation officielle de Gradle.
Astuce : Si votre compilation inclut un grand nombre de tâches personnalisées, vous pouvez désencombrer vos fichiers build.gradle
en créant des classes de tâches personnalisées. Ajoutez vos classes au répertoire project-root/buildSrc/src/main/groovy/
. Gradle les inclura automatiquement dans le chemin des classes pour tous les fichiers build.gradle
de votre projet.
Convertir des images au format WebP
WebP est un format de fichier image qui comprend une compression avec pertes (comme le format JPEG) ainsi qu'une prise en charge de la transparence (comme le format PNG), tout en offrant une meilleure compression que le JPEG ou le PNG.
En réduisant la taille des fichiers image sans avoir à les compresser lors de la compilation, vous pouvez accélérer le processus, en particulier si votre application utilise beaucoup de ressources de ce type. Cependant, vous constaterez peut-être une légère augmentation de l'utilisation du processeur de l'appareil lors de la décompression des images WebP. Utilisez Android Studio pour convertir facilement vos images au format WebP.
Désactiver le traitement PNG
Si vous ne convertissez pas vos images PNG au format WebP, vous pouvez accélérer votre compilation en désactivant la compression automatique des images chaque fois que vous compilez votre application.
Si vous utilisez le plug-in Android Gradle 3.0.0 ou version ultérieure, le traitement PNG est désactivé par défaut pour le type de version de débogage. Pour désactiver cette optimisation pour d'autres types de compilation, ajoutez le code suivant à votre fichier build.gradle
:
Groovy
android { buildTypes { release { // Disables PNG crunching for the "release" build type. crunchPngs false } } }
Kotlin
android { buildTypes { getByName("release") { // Disables PNG crunching for the "release" build type. isCrunchPngs = false } } }
Étant donné que les types de compilation ou les types de produit ne définissent pas cette propriété, vous devez la définir manuellement sur true
lorsque vous créez la version de votre application.
Tester le récupérateur de mémoire en parallèle de la JVM
Vous pouvez améliorer les performances de compilation en configurant le récupérateur de mémoire JVM optimal utilisé par Gradle. Bien que JDK 8 soit configuré par défaut pour utiliser le récupérateur de mémoire en parallèle, JDK 9 et les versions ultérieures utilisent le récupérateur de mémoire G1.
Pour améliorer les performances de compilation, nous vous recommandons de tester vos compilations Gradle avec le récupérateur de mémoire en parallèle. Dans gradle.properties
, définissez les paramètres suivants :
org.gradle.jvmargs=-XX:+UseParallelGC
Si d'autres options sont déjà définies dans ce champ, ajoutez une nouvelle option :
org.gradle.jvmargs=-Xmx1536m -XX:+UseParallelGC
Pour mesurer la vitesse de compilation à l'aide de différentes configurations, consultez la section Effectuer le profilage de votre build.
Augmenter la taille du tas de mémoire de la JVM
En cas de lenteur de la compilation, en particulier lorsque la récupération de mémoire prend plus de 15 % du temps de compilation dans les résultats de Build Analyzer, vous devez augmenter la taille du tas de mémoire de la machine virtuelle Java (JVM)
Dans le fichier gradle.properties
, définissez la limite sur 4, 6 ou 8 gigaoctets comme indiqué dans l'exemple suivant :
org.gradle.jvmargs=-Xmx6g
Testez ensuite l'amélioration de la vitesse de compilation. Le moyen le plus simple de déterminer la taille optimale du tas de mémoire est d'augmenter légèrement la limite, puis de tester si l'amélioration de la vitesse de compilation est suffisante.
Si vous utilisez également le récupérateur de mémoire en parallèle de la JVM, l'intégralité de la ligne doit se présenter comme suit :
org.gradle.jvmargs=-Xmx6g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g
Pour analyser les erreurs de mémoire de la machine virtuelle Java, activez l'option HeapDumpOnOutOfMemoryError. La JVM générera ainsi une empreinte de la mémoire lorsqu'elle sera à court de mémoire.
Utiliser des classes R non transitives
Utilisez des classes R
non transitives afin d'accélérer les compilations pour les applications comportant plusieurs modules. Cela permet d'éviter la duplication des ressources en garantissant que la classe R
de chaque module ne contient que des références à ses propres ressources, sans extraire de références de ses dépendances. Par conséquent, les compilations sont plus rapides et vous bénéficiez des avantages qui découlent de l'évitement de la compilation. Il s'agit du comportement par défaut dans le plug-in Android Gradle 8.0.0 ou version ultérieure.
Depuis Android Studio Bumblebee, les classes R
non transitives sont activées par défaut pour les nouveaux projets.
Pour les projets créés avec des versions antérieures d'Android Studio, mettez-les à jour de manière à utiliser des classes R
non transitives. Pour ce faire, accédez à Refactor > Migrate to Non-Transitive R Classes (Refactoriser > Migrer vers des classes R non transitives).
Pour en savoir plus sur les ressources d'application et les classes R
, consultez la section Présentation des ressources d'application.
Utiliser des classes R non constantes
Utiliser une classe R
non constante
dans les applications et les tests pour améliorer l'incrémentalité de la compilation Java
et permettre une réduction plus précise des ressources. R
champs de classe
ne sont toujours pas constantes pour les bibliothèques, car les ressources sont numérotées
lorsque vous empaquetez l'APK pour l'application ou le test qui dépend de cette bibliothèque.
Il s'agit du comportement par défaut dans le plug-in Android Gradle 8.0.0 ou version ultérieure.
Désactiver l'indicateur Jetifier
Comme la plupart des projets utilisent directement les bibliothèques AndroidX, vous pouvez supprimer l'indicateur Jetifier pour améliorer les performances de compilation. Pour supprimer l'option Jetifier, définissez android.enableJetifier=false
dans votre fichier gradle.properties
.
L'outil Build Analyzer peut vérifier si l'indicateur peut être supprimé en toute sécurité pour améliorer les performances de compilation de votre projet et migrer le système pour ne plus avoir recours à des bibliothèques Android Support qui ne font plus l'objet d'une maintenance. Pour en savoir plus sur Build Analyzer, consultez la section Résoudre les problèmes de performances de compilation.
Utiliser le cache de configuration
La cache de configuration permet à Gradle d'enregistrer des informations sur le graphique des tâches de compilation et de le réutiliser dans les compilations suivantes. Gradle n'a pas besoin de reconfigurer l'ensemble de la compilation.
Pour activer le cache de configuration, procédez comme suit :
- Vérifiez que tous les plug-ins du projet sont compatibles.
Utilisez Build Analyzer pour vérifier si votre projet est compatible avec le cache de configuration. Cet outil exécute une séquence de versions de build pour déterminer si la fonctionnalité peut être activée pour le projet. Consultez le problème n° 13490 pour obtenir la liste des plug-ins compatibles.
Ajoutez le code suivant au fichier
gradle.properties
:org.gradle.configuration-cache=true # Use this flag carefully, in case some of the plugins are not fully compatible. org.gradle.configuration-cache.problems=warn
Lorsque le cache de configuration est activé, la première fois que vous exécutez votre projet, le résultat de la compilation
dit Calculating task graph as no configuration cache is available for tasks
. Pendant
les exécutions suivantes, le résultat de la compilation indique Reusing configuration cache
.
Pour en savoir plus sur le cache de configuration, consultez l'article de blog sur la configuration de la mise en cache et la documentation Gradle à propos du cache de configuration.
Problèmes de cache de configuration introduits dans Gradle 8.1 et le plug-in Android Gradle 8.1
Le cache de configuration est devenu stable dans Gradle 8.1 et l'API de fichier a été introduite
le suivi. Les appels comme File.exists()
, File.isDirectory()
et File.list()
sont enregistrés par
Gradle pour suivre les fichiers d'entrée de configuration.
Le plug-in Android Gradle (AGP) 8.1 utilise ces API File
pour certains fichiers que Gradle doit utiliser
ne sont pas considérées
comme des entrées de cache. Cela déclenche une invalidation supplémentaire du cache lorsqu'il est utilisé avec
Gradle 8.1 et versions ultérieures, ce qui ralentit les performances de compilation.
Les éléments suivants sont traités comme des entrées de cache dans AGP 8.1:
Entrée | Issue Tracker | Corrigé dans |
$GRADLE_USER_HOME/android/FakeDependency.jar | <ph type="x-smartling-placeholder"></ph> Problème 289232054 | AGP 8.2 |
sortie cmake | <ph type="x-smartling-placeholder"></ph> Problème 287676077 | AGP 8.2 |
$GRADLE_USER_HOME/.android/analytics.settings | <ph type="x-smartling-placeholder"></ph> Problème 278767328 | AGP 8.3 |
Si vous utilisez ces API ou un plug-in qui les utilise, vous risquez de rencontrer une régression dans la durée de compilation, car une logique de compilation utilisant ces API peut déclencher une invalidation de cache supplémentaire. Consultez la page <ph type="x-smartling-placeholder"></ph> Améliorations du suivi des entrées pour la configuration de compilation pour en savoir plus sur ces modèles et découvrir comment corriger la logique de compilation, ou désactiver temporairement l'API de suivi des fichiers.