Ottimizza la velocità delle build

Tempi di creazione lunghi rallentano il processo di sviluppo. Questa pagina fornisce alcune tecniche utili per risolvere i colli di bottiglia della velocità di compilazione.

La procedura generale per migliorare la velocità di compilazione della tua app è la seguente:

  1. Ottimizza la configurazione della build adottando alcune passaggi per la maggior parte dei progetti Android Studio.
  2. Crea un profilo della build per identificare e diagnosticare alcuni dei colli di bottiglia più difficili che potrebbero essere specifici del tuo progetto o della tua workstation.

Durante lo sviluppo della tua app, implementala su un dispositivo Android 7.0 (livello API 24) o superiore, se possibile. Le versioni più recenti La piattaforma Android implementa meccanismi migliori per inviare aggiornamenti alla tua app, come l'app Android Runtime (ART) e supporto nativo per più file DEX.

Nota:dopo la prima build, potresti notare che le successive le build, sia pulite che incrementali, funzionano molto più velocemente anche senza utilizzare le ottimizzazioni descritte in questa pagina. Questo perché il daemon Gradle ha un "riscaldamento" periodo di miglioramento delle prestazioni, simile ad altre JVM i processi di machine learning.

Ottimizza la configurazione della build

Segui questi suggerimenti per migliorare la build del tuo progetto Android Studio.

Mantieni aggiornati gli strumenti

Gli strumenti Android ricevono ottimizzazioni delle build e nuove funzionalità con quasi a ogni aggiornamento. Alcuni suggerimenti in questa pagina presuppongono che tu stia utilizzando la versione completamente gestita. Per usufruire delle ultime ottimizzazioni, continua a seguire la procedura riportata di seguito. a oggi:

Usa i punti di forza principali invece di Kapt

Il Kotlin Annotation Processing Tool (kapt) è molto più lento rispetto al modello Symbol Processor (KSP). Se stai scrivendo origini Kotlin annotate e utilizzando strumenti che delle annotazioni dei processi (ad esempio Stanza) che supporta i punti di forza principali, ti consigliamo di eseguire la migrazione al punto di forza principale.

Evita di compilare risorse non necessarie

Evita di compilare e pacchettizzare risorse che non stai testando, ad esempio: localizzazioni linguistiche aggiuntive e risorse per la densità dello schermo. Specifica invece solo uno lingua e densità dello schermo per il tuo "sviluppo" sapore, come mostrato nell'esempio seguente:

Alla moda

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")
        }
        ...
    }
}

Prova a posizionare il portale del plug-in Gradle in ultima analisi

In Android, tutti i plug-in si trovano in google() e mavenCentral() repository. Tuttavia, la build potrebbe hanno bisogno di plug-in di terze parti che vengano risolti utilizzando gradlePluginPortal() completamente gestito di Google Cloud.

Gradle cerca i repository nell'ordine in cui sono dichiarati, quindi le prestazioni della build sono migliori se i repository elencati per primi contengono la maggior parte dei plug-in. Di conseguenza, prova a utilizzare il gradlePluginPortal() inserendola per ultima nel blocco del repository in settings.gradle . Nella maggior parte dei casi, questo riduce al minimo il numero di ricerche di plug-in ridondanti e migliora la velocità di compilazione.

Per saperne di più su come Gradle naviga in più repository, vedi Dichiarare più repository nella documentazione di Gradle.

Utilizzare valori statici di configurazione build con la build di debug

Utilizza sempre valori statici per le proprietà incluse nel file manifest o nei file di risorse di debug del tipo di build.

Usare codici di versione dinamici, nomi di versione, risorse o altro un'altra logica di build che modifica il file manifest richiede una build dell'app completa ogni volta che vuoi eseguire una modifica, anche se la modifica effettiva altrimenti richiedono solo uno "hot swap". Se la configurazione della build richiede proprietà dinamiche, isolale in base alle varianti della build della release e mantieni i valori statici per le build di debug, come mostrato nell'esempio seguente:

  ...
  // 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")
    }
  }

Vedi la ricetta setVersionsFromTask su GitHub per scoprire come impostare un codice di versione dinamico nel progetto.

Usa versioni statiche delle dipendenze

Quando dichiari le dipendenze nei file build.gradle, evita di utilizzare una versione dinamica numeri (quelli che terminano con un segno più, ad esempio 'com.android.tools.build:gradle:2.+'). L'uso dei numeri di versione dinamici può causare aggiornamenti di versione imprevisti e difficoltà a risolvere le versioni differenze e build più lente causate dal controllo della disponibilità di aggiornamenti da parte di Gradle. Utilizza numeri di versione statici.

Creare moduli della libreria

Cerca nella tua app il codice da convertire in un modulo della libreria Android. Modularizzare il codice in questo modo consente al sistema di compilazione di compilare solo i moduli modificati e memorizzarli nella cache per le build future. La modularizzazione semplifica inoltre l'esecuzione parallela dei progetti, più efficace quando attivare quell'ottimizzazione.

Crea attività per la logica di build personalizzata

Dopo aver creato un profilo build, se mostra che una parte relativamente lunga del tempo di compilazione viene dedicata nella **Configurazione di progetto**, esamina gli script build.gradle e cerca il codice da includere in un'attività Gradle personalizzata. Spostando una logica di build in un'attività, aiuti a garantire che l'attività venga eseguita solo quando richiesto e che i risultati possano essere memorizzati nella cache le build successive e la logica di build diventa idonea per l'esecuzione in parallelo se abiliti l'esecuzione parallela di progetti. Per scoprire di più sulle attività per la creazione personalizzata leggi la documentazione ufficiale di Gradle.

Suggerimento:se la build include un numero elevato di attività personalizzate, vuoi riordinare i tuoi file build.gradle creando classi di attività personalizzate. Aggiungi i tuoi corsi al Directory project-root/buildSrc/src/main/groovy/; Gradle include automaticamente queste classi nel classpath per tutti build.gradle file nel progetto.

Converti immagini in WebP

WebP è un file immagine che fornisce una compressione con perdita di dati (come JPEG) e una (ad esempio, PNG). WebP può fornire una compressione migliore rispetto a JPEG o PNG.

Riduzione delle dimensioni dei file immagine senza dover eseguire la compressione in fase di build può velocizzare le build, soprattutto se la tua app usa molte immagini Google Cloud. Tuttavia, potresti notare un lieve aumento dell'utilizzo della CPU del dispositivo la decompressione delle immagini WebP. Usa Android Studio per convertire le tue immagini a WebP.

Disattiva il crunching dei file PNG

Se non converti il file PNG di immagini in WebP, puoi comunque velocizzare la build disattivando e la compressione delle immagini ogni volta che crei la tua app.

Se utilizzi il plug-in Android per Gradle 3.0.0 o superiore, il crunching PNG è disattivato per impostazione predefinita per il "debug" un tipo di build. Per disattivare questa impostazione ottimizzazione per altri tipi di build, aggiungi quanto segue al file build.gradle:

Alla moda

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
        }
    }
}

Poiché i tipi di build o le versioni dei prodotti non definiscono questa proprietà, devi per impostare manualmente questa proprietà su true durante la creazione della release all'ultima versione dell'app.

Sperimenta con il garbage collector parallelo JVM

Le prestazioni della build possono essere migliorate configurando il garbage collector JVM ottimale utilizzato da Gradle. Mentre JDK 8 è configurato per utilizzare il garbage collector parallelo per impostazione predefinita, JDK 9 e versioni successive sono configurato per utilizzare G1 garbage collector.

Per migliorare potenzialmente le prestazioni delle build, ti consigliamo testare le build di Gradle con il garbage collector. In gradle.properties imposta quanto segue:

org.gradle.jvmargs=-XX:+UseParallelGC

Se in questo campo sono già impostate altre opzioni, aggiungi una nuova opzione:

org.gradle.jvmargs=-Xmx1536m -XX:+UseParallelGC

Per misurare la velocità di creazione con configurazioni diverse, consulta Profila la build.

Aumenta la dimensione dello heap JVM

Se noti build lente, in particolare la garbage collection occupa più del 15% il tempo necessario per la creazione Strumento di analisi delle build , devi aumentare la dimensione dello heap della Java Virtual Machine (JVM). Nel file gradle.properties, imposta il limite su 4, 6 o 8 gigabyte come mostrato nell'esempio seguente:

org.gradle.jvmargs=-Xmx6g

Quindi testa il miglioramento della velocità di creazione. Il modo più semplice per determinare l'heap ottimale dimensione è aumentare il limite di una piccola quantità e quindi testare una build sufficiente il miglioramento della velocità.

Se utilizzi anche Gabage Collector parallelo JVM, l'intera riga dovrebbe avere il seguente aspetto:

org.gradle.jvmargs=-Xmx6g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g

Puoi analizzare gli errori di memoria JVM impostando il comando HeapDumpOnOutOfMemoryError attiva il flag. In questo modo, la JVM genererà un dump dell'heap quando la memoria si esaurisce.

Usa classi R non transitive

Usa le classi R non transitive per avere build più veloci per le app con più moduli. Ciò contribuisce a evitare la duplicazione delle risorse garantendo la classe R di ogni modulo contiene solo riferimenti alle proprie risorse senza estrarre riferimenti da e delle sue dipendenze. Questo si traduce in build più rapide e i corrispondenti vantaggi della compilazione elusione. Questo è il comportamento predefinito del plug-in Android per Gradle 8.0.0 e versioni successive.

A partire da Android Studio Bumblebee, le classi R non transitive sono attive per impostazione predefinita per i nuovi progetti. Per i progetti creati con versioni precedenti di Android Studio, aggiornali in modo che utilizzino una versione non transitiva R di classi da Refactoring > Esegui la migrazione alle classi R non temporanee.

Per scoprire di più sulle risorse dell'app e sul corso R, vedi Panoramica delle risorse per app.

Usa classi R non costanti

Utilizza una classe R non costante in app e test per migliorare l'incrementalità della compilazione Java e consentono una riduzione più precisa delle risorse. R campi del corso non sono sempre costanti per le librerie, perché le risorse sono numerate quando pacchettizza l'APK per l'app o il test che dipende da quella libreria. Questo è il comportamento predefinito del plug-in Android Gradle 8.0.0 e versioni successive.

Disattiva il flag Jetifier

Poiché la maggior parte dei progetti utilizza direttamente le librerie AndroidX, puoi rimuovere Flag Jetifier per migliorare le prestazioni della build. Per rimuovere il flag Jetifier, imposta android.enableJetifier=false in gradle.properties file.

Lo strumento di analisi Build può eseguire un controllo per verificare se il flag può essere rimosso in sicurezza per consentire al progetto di migliorare le prestazioni di build ed eseguire la migrazione librerie di supporto Android non mantenute. Per saperne di più sullo Strumento di analisi build, consulta Risolvi i problemi relativi alle prestazioni della build.

Utilizzare la cache di configurazione

La cache di configurazione permette a Gradle di registrare informazioni sul grafico delle attività di build e di riutilizzarle nelle build successive, Gradle non deve riconfigurare l'intera build.

Per attivare la cache di configurazione:

  1. Verifica che tutti i plug-in del progetto siano compatibili.

    Utilizza la Crea lo Strumento di analisi per verificare sia compatibile con la cache di configurazione. Lo Strumento di analisi Build esegue una sequenza di test per determinare se è possibile attivare la funzionalità per il progetto. Consulta problema n. 13490 per un elenco dei plug-in supportati.

  2. Aggiungi il seguente codice al file 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

Quando la cache di configurazione è abilitata, la prima volta che esegui il progetto l'output della build dice Calculating task graph as no configuration cache is available for tasks. Durante successive, l'output della build indica Reusing configuration cache.

Per saperne di più sulla cache di configurazione, consulta il post del blog Approfondimento sulla memorizzazione nella cache della configurazione e la documentazione di Gradle sugli cache di configurazione.

Problemi di configurazione della cache introdotti in Gradle 8.1 e Android Gradle Plugin 8.1

La cache di configurazione è diventata stabile in Gradle 8.1 e ha introdotto un'API per i file il monitoraggio delle conversioni. Chiamate come File.exists(), File.isDirectory() e File.list() vengono registrate da Gradle per monitorare i file di input di configurazione.

Il plug-in Android Gradle (AGP) 8.1 utilizza queste API di File per alcuni file che Gradle dovrebbe non vengono considerati input della cache. Questo attiva un'ulteriore convalida della cache se utilizzata con Gradle 8.1 e versioni successive, con rallentamento delle prestazioni delle build. In AGP 8.1:

Ingresso Monitoraggio problemi Risolto in
$GRADLE_USER_HOME/android/FakeDependency.jar Numero 289232054 AGP 8.2
output cmake Numero 287676077 AGP 8.2
$GRADLE_USER_HOME/.android/analytics.settings Numero 278767328 AGP 8.3

Se utilizzi queste API o un plug-in che le utilizza, potresti riscontrare una regressione in tempo di compilazione, perché alcune logiche di build che utilizzano queste API può attivare un'ulteriore invalidazione della cache. Vedi Miglioramenti al monitoraggio dell'input della configurazione della build per una discussione su questi pattern e su come correggere la logica di build o disattivare temporaneamente il monitoraggio dell'API dei file.