Apps-Grundlage

Migration der Google Play App zu Jetpack Compose

Lautsprecher

  • Kirill Grouchnikov

    Softwareentwickler

  • Jon Boekenoogen

    Softwareentwickler

Info

Über den Vortrag

In diesem Jahr wurde Compose offiziell zur bevorzugten Methode für die Erstellung aller Benutzeroberflächen in Android. Ältere Ansichten befinden sich jetzt im Wartungsmodus. Bei Google Play hat diese Reise bereits 2020 begonnen. Die Migration zu Jetpack Compose wurde durch bewährte Best Practices, eine enge Zusammenarbeit mit dem Compose-Kernteam und eine kontinuierliche Weiterentwicklung der Tools erreicht. Dabei wurde eine Engineering-Infrastruktur berücksichtigt, die sich über fast zwei Jahrzehnte erstreckt und Milliarden von Nutzern umfasst.

Erfahren Sie, wie die Modernisierung von Google Play mit Compose zu messbaren Verbesserungen bei der Geschwindigkeit und langfristigen Stabilität geführt hat. In dieser Session wird gezeigt, wie sich agentische Figma-Design-Workflows mit der Compose-Implementierung verbinden lassen, wie sich die Qualität automatisieren lässt, um unnötige Neuzusammensetzungen zu vermeiden, und wie sich ausdrucksstarke Benutzeroberflächen mit dynamischen Farben, vielfältiger Typografie und mehrschichtigen Formen erstellen lassen. Sie erhalten bewährte Strategien, um Fehler schneller zu beheben und Ihre eigene Compose-Migration zuverlässig zu skalieren.

Zusammenfassung

  • Google Play hat 97 % der Nutzerimpressionen über sechs Jahre hinweg auf reine Compose-Bildschirme verlagert. Auf wichtigen Seiten wurde in den letzten 14 Monaten außerdem eine Verbesserung der Ruckelrate um 30 % festgestellt.
  • Die inkrementelle Einführung minimiert die Geschäftsrisiken bei großen Codebasen. Teams können sich zuerst mit Bildschirmen mit wenig Traffic vertraut machen und dann dazu übergehen, ComposeView direkt im Stammverzeichnis der Aktivität zu hosten.
  • Dynamisches Design funktioniert vollständig im Code mit MaterialTheme-Overlays und der Material Color Utilities-Bibliothek. Dadurch werden Activity-Teardowns vermieden. Das Generieren von Farbschemas während der Build-Zeit trägt jedoch dazu bei, die Laufzeitlatenz zu begrenzen.
  • Der unidirektionale Datenfluss und die deklarative Benutzeroberfläche vereinfachen die Architektur und beseitigen verschiedene Arten von Race-Bedingungen. Durch die parallele Ausführung von Datenquellen und UI-Transformationen konnte die Ladezeit von Google Play um Dutzende Millisekunden verbessert werden.
  • Automatisierte Lint-Prüfungen sorgen für die Einhaltung von Codequalitäts- und Designsystemregeln. Google Play verwendet sie, um hartcodierte Farben zu blockieren und potenzielle Leistungsprobleme wie BoxWithConstraints zu kennzeichnen.

Gemini Notebook

Themen

  • jetpack-compose
  • Migration
  • Leistung
  • nach Thema organisieren
  • unidirectional-data-flow
  • lint-rules
  • developer-velocity

Transkript

Einführung und Einführung im Google Play Store

  • Willkommen in meiner Community!

  • Mein Name ist Jon.

  • Ich bin Mitglied des Google Play Store-Teams.

  • Das ist mein Kollege Kirill.

  • Wir möchten heute darüber sprechen, wie wir einen Großteil des Codes vom View- und Fragment-System zu Compose migriert haben.

  • Legen wir los!

  • Wie lief die Einführung ab und wie groß war der Umfang?

  • Die Codebasis unserer App ist seit etwa 2007 organisch gewachsen.

  • Wir haben über – ein paar Millionen Zeilen Produktionscode, 200 Bildschirme und 500 einzigartige UI-Komponenten, die auf vielen verschiedenen Bildschirmen verwendet werden.

  • Im Jahr 2020 haben wir festgestellt, dass die Entwicklungsgeschwindigkeit, Zuverlässigkeit und Leistung nicht mehr unseren Zielen entsprachen.

  • Also haben wir uns für einen modernen UI-Technologie-Stack entschieden.

  • Wir haben eine Reihe verschiedener Bibliotheken evaluiert.

  • Wir haben uns damals auch mit einigen Freunden bei AndroidX über Compose unterhalten und beschlossen, Compose zu übernehmen und der erste große Partner von Compose zu werden.

  • Wie ist es gelaufen?

  • Sechs Jahre später werden 97 % der Nutzerimpressionen in der Google Play Store App auf Bildschirmen erzielt, die ausschließlich mit Compose erstellt wurden.

  • Seit 2020 wird die Entwicklung für Smartphones und große Bildschirme ausschließlich mit Compose durchgeführt.

  • Und sogar unsere erweiterten Formfaktoren, XR, TV, Auto, Wear, sind seit 2025 auf Compose umgestellt.

  • Compose hat einen großen Anteil an diesem Erfolg und ist der Grund, warum wir es immer mehr einsetzen.

  • Sie hatten eine sehr starke, umfassende Test-Suite, die uns geholfen hat, zweimal pro Woche neue Versionen von Compose zu übernehmen.

  • Durch die Einbindung ihrer Alpha-Builds und neuen APIs können wir neue Fehlerkorrekturen und Leistungsverbesserungen nutzen, einige dieser neuen APIs ausprobieren und neue Funktionen für Nutzer bereitstellen.

  • In Bezug auf die Leistung hat Compose die Ruckler in unserer App auf allen wichtigen Bildschirmen deutlich reduziert.

  • Das sind die Suchergebnisseite, die Startseite und die Detailseite.

  • Diese Messwerte – Leistung, Ruckeln und Ladezeit – sind für unser Unternehmen und auch für die Nutzerfreundlichkeit sehr wichtig.

  • In den letzten 14 Monaten haben wir also eine Verbesserung um 30 % verzeichnet.

Migrationsplan

  • Aber wie kam es dazu?

  • Darum geht es hier eigentlich.

  • Sprechen wir also über den Migrationsplan.

  • Google Play hat daher einen mehrstufigen Ansatz gewählt.

  • Wir wollten nicht alles auf eine Karte setzen.

  • Wir haben uns die Zeit genommen, die Risiken und die Auswirkungen auf unser Unternehmen zu verstehen, und haben Vertrauen aufgebaut, bevor wir uns voll und ganz darauf eingelassen haben.

  • Ich nenne sie: Krabbeln, Gehen, Joggen und Laufen.

  • In der ersten Phase ging es also darum, uns mit Compose vertraut zu machen.

  • Wir haben mit einer Seite mit wenig Traffic begonnen.

  • Das können die Einstellungen, Drittanbieterlizenzen oder Ähnliches sein.

  • Ihr Hauptziel ist es, sich mit der Compose-Bibliothek vertraut zu machen.

  • Sie können sich also mit Zeilen, Spalten, Text, Bildern und all diesen Dingen vertraut machen.

  • Anschließend müssen Sie Ihre gesamte App-Infrastruktur einbinden und verstehen, wie sie mit Compose funktioniert.

  • Das konnte die Protokollierung von Impressionen, die Protokollierung von Klicks, das Design oder die Überarbeitung des Datenladens sein.

  • Also irgendwie alles davon.

  • Besonders hilfreich war es, dafür zu sorgen, dass alle unsere Bildschirme einheitlich aussehen. Wir haben einige Unit-Tests und Funktionstests erstellt, um zu prüfen, ob unsere Designobjekte in Compose direkt den XML-Stilen, der Typografie, den Farben und all diesen Dingen zugeordnet sind.

  • Als wir uns dann etwas besser kannten und uns wohlfühlten, haben wir uns entschieden, spazieren zu gehen.

  • Wir haben eine kleinere Komponente auf einem Bildschirm mit sehr hohem Traffic genommen und uns angesehen, wie eine solche Migration aussehen würde.

  • Wir empfehlen, ein Element aus einer RecyclerView zu nehmen, um Kompatibilitätsprobleme zwischen dem View- und dem Compose-System zu verstehen und die Leistung und das Ruckeln zu messen.

  • Die Komponente selbst muss nicht besonders komplex sein, aber Sie sollten etwas haben, das Layouts, Text, Bilder und ähnliche Dinge verwendet, also ein paar verschiedene Instanzen von dem, was Sie normalerweise sehen würden.

  • In diesem Bereich sollten Sie auf eine leichte Zunahme von Rucklern und Latenz achten, da Sie jetzt zwei Stacks ausführen.

  • Sie haben einen Rendering-Stack, der vollständig in Compose ist, und einen, der in Views ist.

  • Es kommt also zu Speicher-Thrashing, zusätzlichem Laden von Klassen und so weiter.

  • Aber je mehr Sie Compose verwenden, desto weniger wird das der Fall sein.

  • Und wenn Sie es in der Zwischenzeit wirklich benötigen, können Sie den Bildschirm leicht vorwärmen, um ihn in Einklang zu bringen und die Kosten kurzfristig zu senken.

  • Nach dem Gehen kommt das Joggen.

  • Das ist also der Fall, wenn wir uns sehr, sehr sicher sind.

  • Anstatt eine einzelne Komponente auf einer stark frequentierten Seite zu testen, sollten Sie die gesamte stark frequentierte Seite testen.

  • Wir haben also die Navigationsbibliothek und die Fragmente beibehalten, aber für jeden einzelnen Bildschirm wurde die Implementierung vollständig in Compose vorgenommen.

  • Wir haben das Fragment einfach die ComposeView selbst zurückgeben lassen.

  • Sie können also eine verbesserte Latenz und weniger Ruckeln erwarten.

  • Es gibt nicht so viel Speicher-Thrashing und Laden von Klassen, wie ich erwähnt habe.

  • Und Compose selbst führt auch ein gewisses Caching auf der ComposeView-Ebene durch.

  • Wenn Sie also eine RecyclerView mit einer Reihe von Karten haben, die einheitlich aussehen und möglicherweise dieselben Symbole haben, werden alle diese Symbole geparst und die Ressourcennutzung wird von allen Elementen in der ComposeView gemeinsam genutzt.

  • Danach sind wir zum Laufen übergegangen.

  • Jetzt geht es also richtig los.

  • Wenn der Großteil des Traffics Ihrer App über Compose läuft, sind Sie eine Stufe weiter.

  • Über den Bildschirmen befindet sich „Aktivität“.

  • Verschieben Sie die ComposeView also in das Stammverzeichnis der Aktivität.

  • Und ein Großteil Ihres Codes wird relativ ähnlich aussehen.

  • Sie versuchen immer noch, eine Navigationsanweisung zu geben, z. B. „Wechsle von einem Bildschirm zum anderen“.

  • Aber anstatt Fragmenttransaktionen durchzuführen, rufen Sie eine zusammensetzbare Funktion auf.

  • Und das können Sie zusätzlich zur Nav2- oder Nav3-Bibliothek tun, je nachdem, was Sie wählen.

  • Wir hatten nicht alle unsere Bildschirme migriert.

  • Ich habe ja schon erwähnt, dass wir viele davon haben.

  • Wir haben also eine Fragment-Kompatibilität entwickelt, mit der Sie einen fragmentbasierten Bildschirm erstellen und die AndroidFragment-Wrapper von Compose dafür nutzen können.

  • Was Sie erwarten können: Ruckeln und Latenz sind wichtig für unser Geschäft, also haben wir die Grenzen immer weiter verschoben und Sie werden sehen, dass sich das verbessert, weil wir jetzt Caching über Bildschirme hinweg haben und viel weniger von diesem Problem mit dem Speicher-Thrashing.

  • Sie erhalten aber auch neue Funktionen.

  • Rechts sehen Sie ein Beispiel für Übergänge mit gemeinsam genutzten Elementen zwischen Bildschirmen in diesem GIF.

  • Wir haben also ein Bild, das wir vergrößern, wenn Sie von einem Bildschirm zum anderen wechseln, und das sorgt für Kontinuität.

  • Außerdem können Sie während der gesamten Umstellung die Flexibilität von Compose für Animationen nutzen.

  • Damit übergebe ich an Kirill, der Ihnen weitere Funktionen vorstellen wird.

Theming und Leistung

  • Vielen Dank, Jon.

  • Ich möchte ein wenig über ein Thema sprechen, das mir sehr am Herzen liegt: das Design und Styling von Android-Apps. Damit beschäftige ich mich schon seit einiger Zeit.

  • In der View-Welt gab es Java-Code und etwas später Kotlin-Code sowie XML-Ressourcen wie Farben, Strings, Dimensionen, Layouts, Designs und Stile.

  • Dabei wurden alle diese XML-Ressourcen in einer Ressourcentabelle kompiliert, die im APK enthalten war und im Wesentlichen statisch war.

  • Es gab eine API Resources.Theme.applyStyle, die Sie dynamisch zur Laufzeit verwenden konnten, um benutzerdefinierte Stile auf die UI-Hierarchie anzuwenden.

  • Die größte Einschränkung war oder ist, dass Sie dies vor dem Aufblähen Ihrer Inhalte tun müssen. Wenn Sie dieses Styling also dynamisch auf ein vorhandenes UI-Element anwenden möchten, müssen Sie die gesamte Aktivität abbrechen und neu erstellen, was für die Nutzerfreundlichkeit nicht optimal ist.

  • Da diese vorkompilierten XML-Blöcke angewendet wurden, war es außerdem schwierig, mehrere bedingte dynamische Overlays basierend auf Ihren Test-Flags oder anderen geschäftlichen Anforderungen miteinander zu kombinieren.

  • Es war ziemlich schwierig, ein klares mentales Modell der Stilhierarchie in dieser XML-Welt zu entwickeln.

  • Und schließlich gab es in Android Studio oder einem anderen Entwicklungstool keine einheitliche Ansicht, mit der Sie die Lücke zwischen der Java-Welt, der Codewelt und der XML-Welt schließen konnten.

  • Es war schwierig, den Überblick zu behalten, das richtige mentale Modell zu erstellen und herauszufinden, warum mein Stil nicht angewendet wird, warum ich die falsche Farbe erhalte usw.

  • In der neuen Welt, in der Compose-Welt, insbesondere für das Material Design-System und die Compose Material-Bibliothek, aber auch für andere Designsysteme, haben wir für das Material Design-System eine komponierbare Funktion MaterialTheme, die Sie ganz oben in der UI-Hierarchie auf Ihrem Bildschirm anwenden. Sie können diese komponierbare Funktion MaterialTheme auch als Overlay auf einen kleineren Teil Ihrer UI anwenden.

  • Auf dem Bildschirm rechts sehen Sie oben „Play Points Gold“. Das ist eine kleine Karte mit einer Fortschrittsanzeige und etwas Text.

  • Wir wenden dieses Material Theme-Overlay mit einem benutzerdefinierten Farbschema an, das von der Material Color Utilities-Bibliothek generiert wird, die auf GitHub verfügbar ist.

  • Wir übergeben eine Art bräunlich-gelbe, goldene Farbe als Seed und es wird das gesamte Spektrum der Material-Farbtokens generiert, Primärfarbe auf Primärfarbe, Sekundärfarbe auf Sekundärfarbe, die wir dann in der Implementierung dieser Karte verwenden.

  • So können Android-Entwickler die dynamischen Designs in vollem Umfang nutzen.

  • Alles wird im Code und in Kotlin erledigt. Das bedeutet, dass es viel einfacher ist, ein klares mentales Modell der Funktionsweise zu erstellen und Fehler zu beheben.

  • Intern werden diese Overlays als CompositionLocals an die spezifischen UI-Knoten in Ihrer Hierarchie angehängt, auf die Sie sie anwenden möchten.

  • Leistungsaspekte: Das Generieren eines vollständigen Farbschemas mit der Material Color Utilities-Bibliothek ist nicht kostenlos.

  • Es ist mit einem gewissen Aufwand verbunden.

  • Wenn Sie also etwas Komplexes haben, das mehrere davon benötigt, z. B. eine Art Bento-Box oder was auch immer, je nach Ihren Produktanforderungen, und Sie mehrere Farbschemata haben, die zur Laufzeit generiert werden, summiert sich das und führt zu Latenz und Ruckeln.

  • Sie sollten also erstens messen, wie sich das auf die Leistung auswirkt, und zweitens einen Teil dieses Overheads von der Laufzeit auf die Build-Zeit verlagern.

  • Sie können dieselbe Material Color Utilities-Bibliothek zur Build-Zeit verwenden, um diese Farbschemata basierend auf Ihren Branding- oder Produktanforderungen vorab zu generieren und diesen Aufwand auf die Build-Zeit zu verlagern.

  • Die erwähnten CompositionLocals, die verfolgen, wo genau sich die Overlays im UI-Hierarchiebaum befinden, sind viel günstiger, aber immer noch nicht kostenlos.

  • Je nachdem, wie viele Sie davon verwenden, können es Dutzende oder Hunderte sein.

  • Irgendwann sollten Sie sich die Kosten für alle diese kombinierten Kompositionslokale ansehen.

  • Das ist ein Beispiel für die dynamischen Laufzeit-Theming-Funktionen von Compose, die ich erwähnt habe.

  • Hier haben wir vier Quadranten, dieselben Bilder, dieselbe, nennen wir es Ereigniskarte.

  • Wir haben dieses Hero-Image, das sich über die gesamte Karte erstreckt, ein Label oben links, eine Schaltfläche unten rechts und ein paar Texte.

  • Rechts neben jedem Quadranten sehen Sie die Farbtokens, die als Designspezifikation für die einzelnen Elemente verwendet werden.

  • Die Implementierung der Karte ist für alle vier gleich.

  • Der einzige Unterschied besteht darin, dass das Material Theme-Overlay, das die Karte umschließt, mit einem dynamisch erstellten Farbschema generiert oder konfiguriert wird, das auf der dominanten Farbe des Bildes basiert: Blau, Lila, Gelb und Rot.

  • Alles andere bleibt gleich.

  • Sie müssen Ihre Aktivität nicht löschen und neu erstellen.

  • Sie können sie bedingt auf Grundlage Ihrer Test-Flags oder anderer geschäftlicher Anforderungen anwenden.

  • Und wie gesagt, es ist eine viel dynamischere, wirklich dynamische Welt, in der Sie Farbanpassungen auf Ihre App anwenden können.

  • Und jetzt zurück zu Jon für den nächsten Abschnitt.

Zuverlässigkeit und Geschwindigkeit skalieren

  • Ja.

  • Das ist also ein weiterer Aspekt der Flexibilität, von der Kirill gesprochen hat.

  • Sprechen wir über Zuverlässigkeit und Geschwindigkeit.

  • Daher sind alle Entwickler und Unternehmen daran interessiert, schnell hochwertigen Code zu erstellen.

  • Sehen wir uns an, wie Compose Google Play dabei geholfen hat.

  • Zuerst einmal: Ich weiß, dass das ein großes Diagramm ist. Aber die Einfachheit der Architektur hat enorme Vorteile für alle Code-Autoren und -Maintainer, sowohl für Menschen als auch für Agenten.

  • Ich möchte nicht zu sehr ins Detail gehen, aber eines der mentalen Modelle, die Compose zu vermitteln versucht, ist der unidirektionale Datenfluss. Das hat unser Team wirklich stark beeinflusst.

  • Für diejenigen, die mit der Funktionsweise nicht vertraut sind: Sie haben eine Datenquelle.

  • Eine Datenquelle liefert Daten.

  • Diese Daten können in eine bestimmte Benutzeroberfläche umgewandelt werden, die wir als UI-Modell ausgeben.

  • Compose kann das dann ganz einfach beobachten, indem es eine Werteigenschaft für diesen Status aufruft.

  • Das sind die Pfeile oben in diesem Diagramm.

  • Und dann fließen Ereignisse in die entgegengesetzte Richtung.

  • Wenn ein Nutzer also auf eine Schaltfläche klickt, wird dies an den UI-Transformer zurückgegeben, die Datenquelle wird aktualisiert, ein neuer Wert wird ausgegeben, die Transformationen werden ausgeführt und Sie erhalten diese Schleife.

  • Alles läuft also über diese relativ einfache Schleife.

  • Wir haben festgestellt, dass sich dadurch die Anlaufzeit verkürzt.

  • Sie müssen sich nicht mehr fragen, wo all diese Aufrufe im Hauptthread oder in anderen Threads stattfinden.

  • Sie folgt einer allgemeinen Schleife.

  • Compose macht die Datenbeobachtung sehr einfach und die Daten haben starke Konsistenzgarantien über alle Architekturebenen hinweg.

  • Das mentale Modell hat viele Diskussionen über die „Source of Truth“ in unserem Team reduziert und mehrere Arten von Race-Bedingungen vollständig beseitigt.

  • Ein weiterer großer Vorteil im Vergleich zu unserer vorherigen Model-View-Controller-Architektur ist, dass die parallele Ausführung von Datenquellen und UI-Transformationen sehr einfach geworden ist.

  • Dadurch wurde die Ladelatenz im Store um Dutzende Millisekunden verbessert.

  • Das war ziemlich beeindruckend für uns.

  • Neben dem unidirektionalen Datenfluss ist die deklarative UI ein weiterer großer Befürworter von Compose.

  • Kirill hat das bereits kurz angesprochen.

  • Auch Google Play-Entwickler sind von dieser Funktion begeistert.

  • Der Ablauf der UI-Steuerung befindet sich jetzt in einer einzigen Datei.

  • Rechts sehen Sie ein recht einfaches Beispiel.

    @Composable
    fun PurchaseRow(onClick: () -> Unit, modifier: Modifier) {
      Row(modifier) {
        Text("20% off sale")
        if (LocalExpts.current.useButtonV2) {
          ButtonV2("Buy", onClick = onClick)
        } else {
          ButtonV1("Buy", onClick = onClick)
        }
      }
    }
  • Wir wechseln zwischen zwei Schaltflächenimplementierungen basierend auf einem Test-Flag.

  • Anstatt mehrere Ansichtsdateien, Fragmentdateien und XML-Dateien lesen zu müssen, lesen Sie einfach von oben nach unten. Das ist viel einfacher.

  • Die Kosten für das Verschachteln von Composables sind außerdem viel geringer als bei verschachtelten Ansichtshierarchien. Wir können unseren Code so anordnen, dass er besser lesbar ist, anstatt jedes kleine Detail für die Leistung optimieren zu müssen.

  • Ein weiterer Vorteil sind die Lebenszyklus-Callbacks, die viel einfacher geworden sind und von denen es weniger gibt.

  • Anstatt also einen Ansichtslebenszyklus, einen Fragmentlebenszyklus und einen Aktivitätslebenszyklus zu haben, erhalten Sie einen DisposableEffect und einen SideEffect. Je nachdem, wo Sie sie platzieren, verhalten sie sich sehr konsistent.

  • Das ist ein großer Vorteil für uns.

Vorbereitung auf LLMs

  • Diese beiden architektonischen Änderungen haben meiner Meinung nach den Weg für LLMs geebnet und ermöglichen es ihnen, Code von ziemlich hoher Qualität zu generieren.

  • Viele von Ihnen haben das wahrscheinlich schon mit Ihrem bevorzugten LLM ausprobiert.

  • Sie können einen Screenshot mit Farben und Typografie erstellen und ihn eingeben. Sie werden sehen, dass Zeilen, Spalten, Text und Schaltflächen generiert werden können, und das Ergebnis ist ganz passabel.

  • Es gibt jedoch einige Einschränkungen.

  • Google Play versteht Ihre Codebasis nicht, richtig?

  • Es weiß nicht, welche Komponenten Sie bereits erstellt haben und wiederverwenden sollten, und kennt keine Design-Token-Namen.

  • Sie erhalten nur hartcodierte Farben und Strings.

  • Welche Inhalte sollten vom Gerät stammen, welche von einem Server? Wie sorge ich dafür, dass die Leistung bei der Verwendung von LazyList gut ist und nicht nur eine riesige Spalte erstellt wird?

  • Um einige dieser Probleme zu beheben, haben wir die Screenshots mit etwas mehr Metadaten versehen.

  • UI-Namen, Begrenzungsrahmen, damit wir wissen, wo Komponenten beginnen und enden, Design-Tokens für die semantischen Namen von Farben und Typografie, Fähigkeiten und auch einige Prompts, die angeben, wo dies platziert werden soll, damit diese Leistungsaspekte berücksichtigt werden können.

  • Und dann auch nur eine sehr allgemeine Funktionssignatur, damit Sie angeben können, welche Inhalte dynamisch und welche statisch sind.

  • Sie erhalten also etwas Ähnliches wie das, was wir vorher hatten, und wechseln dann zu „Nachher“.

  • Ich habe die Begrenzungsrahmen hier nicht eingefügt, da sie das Diagramm zu unübersichtlich machen würden.

  • Aber Sie können sehen, dass die hartcodierten Farben und Typografienamen durch „title large“ und „on surface“ ersetzt werden.

  • Die Komponentennamen wie Kartenkopf und Symbol-Badge sind deutlich gekennzeichnet.

  • So können diese in Ihrer Codebasis gefunden werden.

  • Viele davon stammen aus gängigen Designbibliotheken, auf die Kirill gleich noch eingehen wird.

  • Sie müssen also nicht alle diese Elemente ständig mit benutzerdefinierten Labels versehen.

  • Wenn Sie das mit einer Methodensignatur wie der unten stehenden (OfferCard) kombinieren, weiß das System, dass der Titel, die endDate und das Bild dynamisch sind.

  • Wir sollten diese nicht hartcodieren.

  • Und zusammen mit diesen semantischen Namen können wir jetzt alle diese verschiedenen Farbanwendungen austauschen, über die Kirill gesprochen hat.

  • Dadurch wird viel mehr Code generiert.

  • Ich übergebe jetzt wieder an Kirill, der darüber sprechen wird, wie wir die Qualität aufrechterhalten.

Qualitätsautomatisierung

  • Genau.

  • Vielen Dank, Jon.

  • Wir bleiben beim Thema LLM und agentengestützte Entwicklung und beginnen mit dem UX-Design.

  • Unabhängig davon, welches Designtool Sie verwenden, ob Figma oder ein anderes, sollten Sie eine gemeinsame Vorlage haben, die von allen Designern verwendet wird und die Farb-Tokens, Typografie-Tokens und Form-Tokens aus dem von Ihnen gewählten Designsystem enthält.

  • Vielleicht ist es Material.

  • Vielleicht ist es dein benutzerdefiniertes Designsystem.

  • Und speziell für die Farb-Tokens möchten Sie, dass diese Vorlagen integrierte Unterstützung für den Wechsel zwischen hellem und dunklem Modus sowie für den Wechsel zwischen den Modi mit normalem, mittlerem und hohem Kontrast bieten, die vor einigen Jahren auf Android-Ebene eingeführt wurden.

  • So können die Designer schnell zwischen diesen verschiedenen Kombinationen wechseln, um zu sehen, wie ihre Designspezifikationen darauf reagieren.

  • Wenn das Design fertiggestellt und an die Implementierung übergeben wird, möchten Sie in dieser Exportpipeline eine Möglichkeit haben, zu prüfen, ob für jede Farbe, jedes Typografieelement und jede Form ein passendes Token verwendet wird, anstatt eines hartcodierten RGB-Werts, einer hartcodierten Schriftfamilie oder einer hartcodierten Schriftgröße.

  • Und schließlich haben wir bei Google Play, wo wir nicht nur Dutzende, sondern Hunderte von Komponenten, Clustern, Karten und Containern haben, die auf einer Vielzahl von Bildschirmen verwendet werden, etwas sehr Nützliches gefunden.

  • Wir haben festgestellt, dass es hilfreich ist, all diese Informationen an einem Ort zu speichern, den wir als Komponentenkatalog bezeichnen, und dann einen benutzerdefinierten Agenten mit diesem Komponentenkatalog zu trainieren.

  • Das ist besonders nützlich, wenn Sie einen neuen Bildschirm, eine neue User Journey oder einen neuen Produktbereich erstellen. Sie können die ersten Designentwürfe, z. B. Folien oder Figma-Spezifikationen, in den KI-Agenten einspeisen. Der KI-Agent hilft dann, schnell zu erkennen, welche Komponenten bereits vorhanden sind, sodass sie nicht neu entworfen, spezifiziert oder implementiert werden müssen.

  • Und das senkt die Design- und Implementierungskosten erheblich.

  • Bei der Implementierung setzen wir stark auf grundlegende und benutzerdefinierte Lint-Regeln.

  • Zwei wichtige Lint-Regeln, die ich hervorheben möchte, sind „FrequentlyChangingValueDetector“, mit der sich Quellen unnötiger Neuzusammensetzungen identifizieren lassen, die zu Latenz und Ruckeln führen können, und „ScaffoldPaddingDetector“, mit der Fälle gekennzeichnet werden, in denen wir die Scaffold-Komposition von Material Compose verwenden, aber die eingehenden Abstände ignorieren.

  • Sie ist keine Quelle für Latenz und Ruckeln, kann aber in einigen Fällen zu sehr schwer zu behebenden Layoutfehlern führen, z. B. bei randlosen Displays oder beim Auf- und Zuklappen.

  • Und schließlich gibt es bei BoxWithConstraints bestimmte Leistungsaspekte, die berücksichtigt werden müssen.

  • Es kann zwei Frames dauern, bis alles richtig angeordnet ist.

  • Wir blockieren es nicht direkt, aber wir kennzeichnen es als Lint-Warnung, damit der Entwickler, der an diesem Bildschirm arbeitet, weiß, dass er sich bewusst für die Verwendung von BoxWithConstraints entscheidet oder vielleicht etwas anderes für dieses Layout verwenden kann.

  • Für die Automatisierung des Designs werden wieder Farb-, Typografie- und Form-Tokens verwendet.

  • Wir haben eine Lint-Regel, die die Verwendung von hartcodierten Farben und hartcodierter Typografie blockiert.

  • Wir haben eine Lint-Regel, die die Verwendung von Material 2-Komponenten kennzeichnet.

  • Wir möchten nur Material 3 verwenden, die neueste und beste Version, einschließlich der neuen ausdrucksstarken Komponenten, die letztes und dieses Jahr eingeführt wurden.

  • Wir haben eine benutzerdefinierte Lint-Regel, die verhindert, dass Farben aus alten XML-Dateien gelesen werden.

  • Wir möchten für neue Bildschirme Compose-first und Compose-only verwenden.

  • Und Text-Kompositionen, insbesondere im Material Design-System, haben Fallbacks für Stil und Farbe.

  • Sie lesen sie aus der lokalen Inhaltsfarbe und der lokalen Typografie, aber wir möchten uns nicht darauf verlassen.

  • Jeder einzelne Text soll den spezifischen Stil, die Typografie und die Farbe aus der Designspezifikation verwenden.

  • Das ist also eine Lint-Regel, die wir haben.

  • Und schließlich haben wir, ähnlich wie beim ScaffoldPaddingDetector, eine benutzerdefinierte Lint-Regel, die erzwingt, dass jede einzelne zusammensetzbare Funktion, die wir haben, ihren Eingabemodifikator verwendet.

  • So wird verhindert, dass neue Elemente falsch platziert werden oder der Hintergrund nicht berücksichtigt wird.

Fazit

  • Das sind die drei wichtigsten Punkte, die Sie aus dieser Präsentation mitnehmen sollten.

  • Erstens: Heute, Ende 2026, ist Compose unserer Meinung nach ein ausgereiftes UI-Toolkit, das sich im großen Maßstab bewährt hat.

  • Android selbst ist Compose-first.

  • Anfang des Jahres haben wir auf der Google I/O angekündigt, dass alle UI-Bibliotheken und alle agentischen Abläufe Compose-First sind.

  • Und wie Jon bereits erwähnt hat, empfehlen wir, schrittweise zu migrieren, insbesondere bei großen Codebasen, um die Geschwindigkeit für Entwickler- und Agentenabläufe zu erhöhen.

  • Vielen Dank, dass Sie sich heute Zeit für uns genommen haben. Jon und ich werden in ein paar Minuten draußen sein, um Ihre Fragen zu beantworten.

  • Vielen Dank für Ihre Zeit.

Code

Code-Snippets

Kotlin-Snippet bei 16:09 in „Scaling reliability and velocity“
@Composable
fun PurchaseRow(onClick: () -> Unit, modifier: Modifier) {
  Row(modifier) {
    Text("20% off sale")
    if (LocalExpts.current.useButtonV2) {
      ButtonV2("Buy", onClick = onClick)
    } else {
      ButtonV1("Buy", onClick = onClick)
    }
  }
}