Build-Geschwindigkeit optimieren

Lange Build-Zeiten verlangsamen den Entwicklungsprozess. Auf dieser Seite finden Sie einige Methoden, bei der Build-Geschwindigkeit.

Im Allgemeinen gehen Sie so vor, um die Build-Geschwindigkeit Ihrer App zu verbessern:

  1. Optimieren Sie Ihre Build-Konfiguration, indem Sie die den meisten Android Studio-Projekten unmittelbar zugute kommen.
  2. Erstellen Sie ein Profil für Ihren Build, um einige zu ermitteln und zu diagnostizieren. die möglicherweise kniffliger sind.

Stellen Sie Ihre App bei der Entwicklung auf einem Android-Gerät bereit. 7.0 (API-Level 24) oder höher, wann immer möglich. Neuere Versionen des Android-Plattform implementiert bessere Mechanismen zum Übertragen von Updates für Ihre App, wie die Android- Laufzeit (ART) und native Unterstützung für mehrere DEX-Dateien.

Hinweis:Nach Ihrem ersten sauberen Build stellen Sie möglicherweise fest, dass nachfolgende sowohl saubere als auch inkrementelle Builds, arbeiten viel schneller, sogar ohne die auf dieser Seite beschriebenen Optimierungen. Das liegt daran, dass der Gradle-Daemon hat eine „Aufwärmphase“, Zeitraum mit Leistungsanstieg (ähnlich wie bei anderen JVM) Prozesse.

Build-Konfiguration optimieren

Befolgen Sie diese Tipps, um den Build zu verbessern Ihres Android Studio-Projekts.

Tools auf dem neuesten Stand halten

Die Android-Tools erhalten Build-Optimierungen und neue Funktionen mit fast bei jedem Update. Bei einigen Tipps auf dieser Seite wird davon ausgegangen, Version. Um von den neuesten Optimierungen zu profitieren, sollten Sie Bis heute:

KSP anstelle von kapt verwenden

Das Kotlin Annotation Processing Tool (kapt) ist wesentlich langsamer als das Kotlin Annotation Processing Tool (kapt). Symbol Processor (KSP). Wenn Sie eine annotierte Kotlin-Quelle schreiben und Tools verwenden, verarbeitet Anmerkungen (z. B. Room) der KSP unterstützt, müssen Sie zum KSP migrieren.

Kompilieren unnötiger Ressourcen vermeiden

Vermeiden Sie das Kompilieren und Packen von Ressourcen, die Sie nicht testen, z. B. zusätzliche Sprachlokalisierungen und Ressourcen zur Bildschirmdichte. Geben Sie stattdessen nur eine Sprachressource und Bildschirmdichte für deinen „dev“ Geschmacksrichtung, wie im folgenden Beispiel gezeigt:

Cool

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

Experimentieren Sie, um das Gradle-Plug-in-Portal zuletzt zu platzieren

In Android befinden sich alle Plug-ins in google() und mavenCentral() Repositories. Ihr Build könnte jedoch Drittanbieter-Plug-ins benötigen, die mithilfe der gradlePluginPortal() .

Gradle sucht in Repositories in der Reihenfolge, in der sie deklariert sind. sodass die Build-Leistung verbessert wird, wenn die zuerst aufgeführten Repositories der meisten Plug-ins. Experimentieren Sie daher mit gradlePluginPortal() fügen Sie ihn an letzter Stelle im Repository-Block Ihres settings.gradle ein. -Datei. In den meisten Fällen minimiert dies die Anzahl redundanter Plug-in-Suchen und die Build-Geschwindigkeit verbessern.

Weitere Informationen dazu, wie Gradle durch mehrere Repositories navigiert, findest du unter Mehrere Repositories deklarieren in der Gradle-Dokumentation.

Statische Build-Konfigurationswerte mit dem Debug-Build verwenden

Verwenden Sie immer statische Werte für Eigenschaften, die in der Manifest-Datei oder den Ressourcendateien für Ihr Debug-Build-Typ.

Verwendung dynamischer Versionscodes, Versionsnamen, Ressourcen oder anderer Andere Build-Logik, die die Manifestdatei ändert, erfordert einen vollständigen App-Build. wenn Sie eine Änderung vornehmen möchten, selbst wenn die und andernfalls nur einen Hot Swap erforderlich ist. Wenn für Ihre Build-Konfiguration Folgendes erforderlich ist: dynamische Eigenschaften und isolieren Sie diese Eigenschaften dann für Ihre Release-Build-Varianten. die statischen Werte für Ihre Debug-Builds, wie im folgenden Beispiel gezeigt:

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

Im setVersionsFromTask-Schema auf GitHub erfahren Sie, wie Sie dynamischen Versionscode in Ihrem Projekt.

Statische Abhängigkeitsversionen verwenden

Vermeiden Sie die Verwendung der dynamischen Version, wenn Sie Abhängigkeiten in Ihren build.gradle-Dateien deklarieren Zahlen (mit einem Pluszeichen am Ende, z. B. 'com.android.tools.build:gradle:2.+'). Die Verwendung dynamischer Versionsnummern kann zu unerwarteten Versionsupdates und Problemen beim Auflösen der Version führen. und langsamere Builds aufgrund der Suche nach Updates durch Gradle. Verwenden Sie stattdessen statische Versionsnummern.

Bibliotheksmodule erstellen

Suchen Sie in Ihrer App nach Code, den Sie in ein Android-Bibliotheksmodul konvertieren können. Durch die Modularisierung Ihres Codes auf diese Weise kann das Build-System nur die Module, die Sie ändern, und speichern diese Ausgaben für zukünftige Builds im Cache. Modularisierung sorgt außerdem dafür, parallelen Projektausführung effektiver, wenn Sie um diese Optimierung zu ermöglichen.

Aufgaben für benutzerdefinierte Build-Logik erstellen

Wenn nach der Erstellung eines Build-Profils der Build zeigt, dass ein relativ langer Teil der Build-Zeit auf die Seite **Konfigurieren Projekt**-Phase ist, überprüfen Sie Ihre build.gradle-Skripts und suchen Sie Code für eine benutzerdefinierte Gradle-Aufgabe. Durch Verschieben einer Build-Logik in eine Aufgabe umwandeln, stellen Sie sicher, dass die Aufgabe nur bei Bedarf ausgeführt wird, die Ergebnisse können für nachfolgende Builds. Diese Build-Logik kann parallel ausgeführt werden, wenn Sie die parallele Projektausführung aktivieren. Weitere Informationen zu Themen für benutzerdefinierte Builds finden Sie in der offiziellen Gradle-Dokumentation.

Tipp:Wenn Ihr Build eine große Anzahl von benutzerdefinierten Aufgaben enthält, können Sie Sie Ihre build.gradle-Dateien aufräumen möchten, indem Sie benutzerdefinierte Aufgabenklassen erstellen. Fügen Sie Ihre Kurse hinzu: project-root/buildSrc/src/main/groovy/-Verzeichnis; Gradle fügt diese Klassen automatisch in den classpath für alle build.gradle-Dateien in Ihrem Projekt.

Bilder in WebP konvertieren

WebP ist eine Bilddatei. Format, das eine verlustbehaftete Komprimierung (wie JPEG) und Transparenz bietet (z. B. PNG). WebP bietet eine bessere Komprimierung als JPEG oder PNG.

Reduzieren der Größe von Bilddateien, ohne eine Komprimierung bei der Build-Erstellung durchführen zu müssen kann Ihre Builds beschleunigen, vor allem, wenn Ihre App viele Bild-Assets Ressourcen. Es kann jedoch sein, dass Sie während beim Dekomprimieren von WebP-Bildern. Mit Android Studio können Sie konvertieren Sie Ihre Bilder an WebP übertragen.

Verarbeitung von PNG-Dateien deaktivieren

Wenn Sie Ihre PNG-Datei nicht konvertieren Bilder zu WebP übertragen, können Sie Ihren Build trotzdem beschleunigen, indem Sie die automatische Bildkomprimierung bei jeder App-Erstellung.

Wenn Sie das Android-Gradle-Plug-in 3.0.0 verwenden oder höher ist die Verarbeitung von PNG-Dateien für den "debug"-Parameter standardmäßig deaktiviert. Build-Typ. So deaktivieren Sie diese Funktion: Optimierung für andere Build-Typen verwenden, fügen Sie der Datei build.gradle Folgendes hinzu:

Cool

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

Da diese Eigenschaft für Build-Typen oder Produkt-Geschmacksrichtungen nicht definiert wird, benötigen Sie um dieses Attribut beim Erstellen des Release manuell auf true festzulegen Version Ihrer App.

Mit der parallelen automatischen Speicherbereinigung von JVM experimentieren

Die Build-Leistung kann verbessert werden, indem Sie den optimalen von Gradle verwendeten Garbage Collector von JVM konfigurieren. Während JDK 8 standardmäßig so konfiguriert ist, dass die parallele automatische Speicherbereinigung verwendet wird, sind JDK 9 und höher konfiguriert, um G1 Garbage Collector

Um die Build-Leistung potenziell zu verbessern, empfehlen wir Gradle-Builds testen mit dem parallelen für die automatische Speicherbereinigung. Legen Sie in gradle.properties Folgendes fest:

org.gradle.jvmargs=-XX:+UseParallelGC

Wenn in diesem Feld bereits andere Optionen festgelegt sind, fügen Sie eine neue Option hinzu:

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

Informationen zum Messen der Build-Geschwindigkeit mit verschiedenen Konfigurationen finden Sie unter Erstellen Sie ein Profil für Ihren Build.

<ph type="x-smartling-placeholder">

JVM-Heap-Größe erhöhen

Wenn Sie langsame Builds beobachten und insbesondere die automatische Speicherbereinigung mehr als 15% des die Zeit in der Build-Analysetool sollten Sie die Größe des Java Virtual Machine (JVM)-Heaps erhöhen. Legen Sie in der Datei gradle.properties das Limit auf 4, 6 oder 8 Gigabyte fest. Dies wird im folgenden Beispiel gezeigt:

org.gradle.jvmargs=-Xmx6g

Testen Sie dann, ob sich die Build-Geschwindigkeit verbessert hat. Die einfachste Methode, den optimalen Heap zu bestimmen das Limit geringfügig zu erhöhen und dann zu testen, ob ein ausreichender Build um die Geschwindigkeit zu erhöhen.

<ph type="x-smartling-placeholder">

Wenn Sie auch das Parallele automatische Speicherbereinigung von JVM sollte die gesamte Zeile so aussehen:

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

Sie können die JVM-Arbeitsspeicherfehler analysieren, indem Sie den Fehler HeapDumpOnOutOfMemoryError aktivieren aktiviert. Dadurch generiert die JVM einen Heap-Dump, wenn nicht genügend Arbeitsspeicher vorhanden ist.

Nicht transitive R-Klassen verwenden

Verwenden Sie nicht transitive R-Klassen für schnellere Builds für Apps mit mehreren Modulen. So vermeiden Sie Duplikate von Ressourcen, Die R-Klasse jedes Moduls enthält nur Verweise auf seine eigenen Ressourcen, ohne dass Verweise aus ihre Abhängigkeiten. Dies führt zu schnelleren Builds und den entsprechenden Vorteilen der Kompilierung. zu vermeiden. Dies ist das Standardverhalten im Android-Gradle-Plug-in 8.0.0 und höher.

Ab Android Studio Bumblebee sind nicht transitive R-Klassen standardmäßig für neue Projekte aktiviert. Aktualisieren Sie Projekte, die mit älteren Versionen von Android Studio erstellt wurden, um die nicht transitiven Versionen zu verwenden. R, indem Sie zu Refaktorieren > Zu Non-Transitive R-Klassen migrieren

Weitere Informationen zu App-Ressourcen und zur Klasse R findest du unter Übersicht über App-Ressourcen.

Nicht konstante R-Klassen verwenden

Konstante R-Klasse verwenden Felder in Anwendungen und Tests, um die Steigerung der Conversions bei der Java-Kompilierung zu verbessern und ermöglichen eine präzisere Verkleinerung von Ressourcen. R Klassenfelder sind für Bibliotheken nicht gleich, da die Ressourcen nummeriert sind. wenn Sie das APK für die App verpacken oder testen, der von dieser Bibliothek abhängt. Dies ist das Standardverhalten im Android-Gradle-Plug-in ab Version 8.0.0.

Jetifier-Flag deaktivieren

Da die meisten Projekte AndroidX-Bibliotheken direkt nutzen, können Sie die Jetifier-Flag für eine bessere Build-Leistung. Entfernen Jetifier-Flag verwenden, legen Sie android.enableJetifier=false in Ihrem gradle.properties-Datei.

Der Build Analyzer kann prüfen, ob das Flag sicher entfernt werden, damit Ihr Projekt eine bessere Leistung erzielen und eine Migration weg vom nicht gewartete Android-Supportbibliotheken. Weitere Informationen zu Build Analyzer finden Sie unter Fehler bei der Build-Leistung beheben

Konfigurationscache verwenden

Die Konfigurationscache kann Gradle Informationen über die Grafik der Build-Aufgaben aufzeichnen und in nachfolgenden Builds wiederverwenden, Gradle muss nicht den gesamten Build neu konfigurieren.

So aktivieren Sie den Konfigurationscache:

  1. Prüfen Sie, ob alle Projekt-Plug-ins kompatibel sind.

    Verwenden Sie die Methode Build Analyzer zur Prüfung, ob Ihre Projekt ist mit dem Konfigurations-Cache kompatibel. Build Analyzer führt eine Reihe von Tests aus um festzustellen, ob die Funktion für das Projekt aktiviert werden kann. Weitere Informationen finden Sie unter Problem Nr. 13490 für eine Liste der unterstützten Plug-ins.

  2. Fügen Sie der Datei gradle.properties den folgenden Code hinzu:

      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

Wenn der Konfigurationscache aktiviert ist, wird beim ersten Ausführen Ihres Projekts die Build-Ausgabe sagt Calculating task graph as no configuration cache is available for tasks. Währenddessen nachfolgende Ausführungen führt, lautet die Build-Ausgabe Reusing configuration cache.

Weitere Informationen zum Konfigurationscache finden Sie im Blogpost. Konfigurations-Caching im Detail und in der Gradle-Dokumentation Konfigurationscache.

Probleme beim Konfigurationscache in Gradle 8.1 und Android-Gradle-Plug-in 8.1

Der Konfigurationscache wurde in Gradle 8.1 stabil und die Datei-API wurde eingeführt. Verfolgung. Anrufe wie File.exists(), File.isDirectory() und File.list() werden aufgezeichnet von Gradle zum Verfolgen der Konfigurationseingabedateien.

Das Android-Gradle-Plug-in (AGP) 8.1 verwendet diese File-APIs für einige Dateien, die Gradle verwenden soll. nicht als Cache-Eingaben betrachtet werden. Dies führt zu einer zusätzlichen Cache-Entwertung bei Verwendung mit Gradle 8.1 und höher, wodurch die Build-Leistung verlangsamt wird. Folgendes wird in AGP 8.1 als Cache-Eingaben behandelt:

Eingang Issue Tracker Festgelegt in
$GRADLE_USER_HOME/android/FakeDependency.jar <ph type="x-smartling-placeholder"></ph> Problem 289232054 8.2 AGP
Ausgabe erstellen <ph type="x-smartling-placeholder"></ph> Problem 287676077 8.2 AGP
$GRADLE_USER_HOME/.android/analytics.settings <ph type="x-smartling-placeholder"></ph> Problem 278767328 8.3 AGP

Wenn Sie diese APIs oder ein Plug-in verwenden, das diese APIs verwendet, kann es zu einer Regression der Build-Zeit kommen, da einige Build-Logik mit diesen APIs kann eine weitere Cache-Entwertung auslösen. Weitere Informationen finden Sie unter <ph type="x-smartling-placeholder"></ph> Verbesserungen beim Eingabe-Tracking für die Build-Konfiguration finden Sie weitere Informationen zu diesen Mustern und dazu, wie Sie die Build-Logik korrigieren oder den Datei-API-Tracking.