Principes de base des applications

Migrer l'application Google Play vers Jetpack Compose après deux décennies d'existence

Haut-parleurs

  • Kirill Grouchnikov

    Ingénieur logiciel

  • Jon Boekenoogen

    Ingénieur logiciel

À propos

À propos de l'intervention

Cette année, Android est officiellement devenu Compose-first pour la création de toutes les interfaces utilisateur, et les anciennes vues sont passées en mode de maintenance. Pour Google Play, ce parcours a commencé en 2020. La migration vers Jetpack Compose, qui s'est appuyée sur une expérience d'ingénierie de près de deux décennies et des milliards d'utilisateurs, a été réalisée grâce à des bonnes pratiques éprouvées, une collaboration étroite avec l'équipe principale de Compose et une évolution continue des outils.

Découvrez comment la modernisation de Google Play avec Compose a permis d'améliorer de manière mesurable la rapidité et la stabilité à long terme. La session explique comment connecter les workflows de conception Figma agentiques à l'implémentation Compose, automatiser la qualité pour éviter les recompositions inutiles et créer des interfaces expressives avec des couleurs dynamiques, une typographie riche et des formes superposées. Vous repartirez avec des stratégies testées pour trier les bugs plus rapidement et faire évoluer votre propre migration vers Compose en toute confiance.

Résumé

  • Google Play a migré 97 % des impressions utilisateur vers des écrans Compose uniquement en six ans. Les pages principales ont également enregistré une amélioration de 30 % du taux de saccades au cours des 14 derniers mois.
  • L'adoption incrémentielle limite les risques métier dans les codebases volumineux. Les équipes peuvent d'abord se familiariser avec les écrans à faible trafic, puis passer à l'hébergement de ComposeView directement à la racine de l'activité.
  • La thématisation dynamique fonctionne entièrement dans le code à l'aide de superpositions MaterialTheme et de la bibliothèque Material Color Utilities. Cela évite les destructions d'activités, bien que la génération de jeux de couleurs au moment de la compilation permette de limiter la latence d'exécution.
  • Le flux de données unidirectionnel et l'UI déclarative simplifient l'architecture et éliminent plusieurs types de conditions de concurrence. L'exécution en parallèle des sources de données et des transformations de l'UI a permis d'améliorer la latence de chargement de Google Play de plusieurs dizaines de millisecondes.
  • Les vérifications Lint automatisées appliquent les règles de qualité du code et du système de conception. Play les utilise pour bloquer les couleurs codées en dur et signaler les problèmes de performances potentiels tels que BoxWithConstraints.

Gemini Notebook

Thèmes

  • jetpack-compose
  • migration
  • performance
  • thématisation
  • unidirectional-data-flow
  • lint-rules
  • developer-velocity

Transcription

Introduction et adoption du Google Play Store

  • Bienvenue !

  • Je m'appelle Jon.

  • Je fais partie de l'équipe Google Play Store.

  • Voici mon collègue Kirill.

  • Nous sommes ici aujourd'hui pour vous expliquer comment nous avons migré une grande partie du code du système View et Fragment vers Compose.

  • C'est parti !

  • Comment s'est passée cette adoption et quelle a été son ampleur ?

  • Le codebase de notre application s'est développé de manière organique depuis environ 2007.

  • Nous avons plus de quelques millions de lignes de code de production, 200 écrans et 500 composants d'interface utilisateur uniques qui sont utilisés sur un grand nombre de ces écrans.

  • En 2020, nous avons constaté que la vélocité, la fiabilité et les performances des développeurs ne permettaient pas d'atteindre les objectifs que nous nous étions fixés.

  • Nous avons donc décidé d'adopter une pile technologique d'UI moderne.

  • Nous avons évalué plusieurs bibliothèques.

  • Nous avons également discuté avec des amis d'AndroidX à propos de Compose à l'époque, et nous avons décidé d'adopter Compose et de devenir son premier partenaire majeur.

  • Comment ça s'est passé ?

  • Six ans plus tard, 97 % des impressions utilisateur dans l'application Play Store sont générées sur des écrans Compose uniquement.

  • En fait, depuis 2020, tout le développement pour les téléphones et les grands écrans est passé à Compose uniquement.

  • Et même nos facteurs de forme étendus, XR, TV, Auto et Wear, sont passés à Compose depuis 2025.

  • Compose a joué un rôle majeur dans cette réussite, et c'est pourquoi nous l'adoptons de plus en plus.

  • Ils disposent d'une suite de tests très complète et efficace qui nous a aidés à adopter de nouvelles versions de Compose deux fois par semaine.

  • En intégrant leurs versions alpha et leurs nouvelles API, nous pouvons profiter de nouvelles corrections de bugs et améliorations des performances, et vraiment explorer certaines de ces nouvelles API pour offrir de nouvelles expériences utilisateur.

  • En ce qui concerne les performances, Compose a vraiment permis d'améliorer les performances de notre application sur tous nos écrans principaux.

  • Il s'agit de la page de résultats de recherche, de la page d'accueil et de la page d'informations.

  • Ces métriques (performances, saccades et latence de chargement) sont très importantes pour notre activité et pour l'expérience utilisateur.

  • Nous avons donc constaté une amélioration de 30 % au cours des 14 derniers mois.

Plan de migration

  • Mais comment en sommes-nous arrivés là ?

  • C'est ce dont nous allons parler aujourd'hui.

  • Parlons du plan de migration.

  • Play a donc adopté une approche en plusieurs étapes.

  • Nous ne voulions pas nous lancer tête baissée et mettre tous nos œufs dans le même panier, pour ainsi dire.

  • Nous avons donc pris quelques mesures pour comprendre les risques et leur impact sur notre activité, et pour vraiment gagner en confiance avant de nous lancer.

  • Je vais donc les nommer : ramper, marcher, trottiner et courir.

  • Pour nous, la première étape consistait à nous familiariser avec Compose.

  • Nous avons commencé par une page à faible trafic.

  • Il peut s'agir de la page des paramètres, des licences tierces, etc.

  • Votre objectif principal est de vous familiariser avec la bibliothèque Compose.

  • Vous pouvez ainsi vous habituer aux lignes, aux colonnes, au texte, aux images, etc.

  • Ensuite, vous devez commencer à intégrer l'infrastructure de votre application et à comprendre comment elle fonctionne avec Compose.

  • Il pouvait s'agir de la journalisation des impressions, de la journalisation des clics, de la thématisation, ou de la refonte du chargement des données.

  • En fait, un peu tout ça.

  • Pour nous assurer que tous nos écrans sont cohérents, nous avons créé des tests unitaires et fonctionnels afin de vérifier que nos objets de thème dans Compose correspondent directement aux styles XML, à la typographie, aux couleurs, etc.

  • Une fois que nous nous sommes familiarisés avec le terrain et que nous nous sommes sentis à l'aise, nous avons décidé de passer à la marche.

  • Pour nous, cela consistait à prendre un composant plus petit sur un écran à très fort trafic et à évaluer à quoi ressemblait ce type de migration.

  • Nous vous recommandons de prendre un élément d'un RecyclerView. Vous pourrez ainsi comprendre les problèmes de compatibilité entre le système View et le système Compose, et mesurer les performances et les à-coups en cours de route.

  • Le composant lui-même n'a pas besoin d'être très complexe, mais vous devez vraiment avoir quelque chose qui utilise des mises en page, du texte, des images, etc., quelques instances différentes de ce que vous verriez normalement.

  • Vous devez vous attendre à une légère augmentation des à-coups et de la latence, car vous exécutez désormais deux piles.

  • Vous disposez d'une pile de rendu entièrement dans Compose et d'une autre dans Views.

  • Il y aura donc un certain écrasement de la mémoire, un chargement de classe supplémentaire, etc.

  • Mais à mesure que vous adopterez Compose, ce problème disparaîtra.

  • Si vous en avez vraiment besoin entre-temps, vous pouvez préchauffer légèrement cet écran pour l'aligner et réduire ce coût à court terme.

  • Après la marche, nous passons au jogging.

  • C'est une fois que nous sommes devenus très, très à l'aise.

  • Au lieu de créer un seul composant sur une page à fort trafic, créez l'intégralité de la page à fort trafic.

  • Nous avons donc conservé la bibliothèque de navigation et l'utilisation des fragments, mais chaque écran a été entièrement implémenté dans Compose.

  • Nous avons simplement demandé au fragment de renvoyer la vue ComposeView elle-même.

  • Vous pouvez donc vous attendre à une amélioration de la latence et des à-coups.

  • Vous n'avez pas autant de problèmes de mémoire et de chargement de classe que ceux dont je parlais.

  • Compose effectue également une mise en cache à certains niveaux au niveau de ComposeView.

  • Ainsi, si vous avez un RecyclerView avec un ensemble de fiches qui ont l'air cohérentes et qui peuvent avoir les mêmes icônes, l'analyse de ces icônes et l'utilisation des ressources sont partagées entre tous les éléments de la ComposeView.

  • Après cela, nous sommes passés à la course à pied.

  • C'est à ce moment-là que vous devez vraiment vous lancer.

  • Une fois que la majeure partie du trafic de votre application est passée à Compose, nous sommes passés au niveau supérieur.

  • Au-dessus de "Écrans", nous avons "Activité".

  • Déplacez donc ComposeView vers la racine de l'activité.

  • Une grande partie de votre code sera relativement similaire.

  • Vous essayez toujours d'effectuer une instruction de navigation pour passer d'un écran à un autre.

  • Mais au lieu d'effectuer des transactions de fragment, vous appelez une fonction composable.

  • Vous pouvez le faire en plus de la bibliothèque Nav2 ou Nav3, selon votre choix.

  • Dans notre cas, nous n'avions pas migré tous nos écrans.

  • Je vous avais dit qu'il y en avait beaucoup.

  • Nous avons donc développé la compatibilité avec les fragments. Vous pouvez ainsi avoir un écran basé sur des fragments et utiliser les wrappers AndroidFragment de Compose pour ce faire.

  • Comme je l'ai dit, les saccades et la latence sont importantes pour notre activité. Nous avons donc continué à repousser les limites, et vous constaterez que nous continuons à nous améliorer, car nous disposons désormais d'une mise en cache sur tous les écrans et d'un problème de thrashing de mémoire beaucoup moins important.

  • Mais vous bénéficiez également de nouvelles fonctionnalités.

  • Vous pouvez en voir un exemple à droite dans ce GIF, où vous pouvez effectuer des transitions d'éléments partagés entre les écrans.

  • Nous avons donc une image que nous agrandissons lorsque vous passez d'un écran à l'autre, ce qui assure cette continuité.

  • Vous pouvez également exploiter toute la flexibilité d'animation de Compose pendant cette transition.

  • Je passe maintenant la parole à Kirill, qui va vous présenter d'autres fonctionnalités.

Thématisation et performances

  • Merci, Jon.

  • Je voudrais vous parler d'un sujet qui me tient particulièrement à cœur : les thèmes et les styles pour les applications Android, un domaine dans lequel je travaille depuis un certain temps déjà.

  • Dans le monde des vues, il y avait du code Java et, un peu plus tard, du code Kotlin, puis des ressources XML, telles que des couleurs, des chaînes, des dimensions, des mises en page, des thèmes et des styles.

  • Toutes ces ressources XML étaient compilées dans une table de ressources incluse dans l'APK, et elles étaient plutôt statiques.

  • Il existait une API Resources.Theme.applyStyle que vous pouviez utiliser de manière dynamique au moment de l'exécution pour appliquer un style personnalisé au-dessus de la hiérarchie de l'UI.

  • La principale limite était (et est toujours) que vous devez le faire avant d'intégrer votre contenu. Autrement dit, si vous souhaitez appliquer ce style de manière dynamique à un élément d'interface utilisateur existant, vous devez supprimer et recréer l'intégralité de l'activité, ce qui n'est pas idéal pour l'expérience utilisateur.

  • De plus, comme il appliquait ces blocs XML précompilés, il devenait difficile de combiner plusieurs superpositions dynamiques conditionnelles les unes sur les autres en fonction de vos indicateurs de test ou de tout autre besoin métier.

  • Il était assez difficile de créer un modèle mental approprié de la hiérarchie des styles dans ce monde XML.

  • Enfin, il n'existait pas de vue unifiée unique dans Android Studio ni dans aucun autre outil pour les développeurs permettant de combler l'écart entre le monde Java, le monde du code et le monde XML.

  • Il était difficile de jongler entre les deux, de créer le bon modèle mental et de comprendre pourquoi mon style n'était pas appliqué, pourquoi j'obtenais la mauvaise couleur, etc.

  • Dans le nouveau monde, celui de Compose, en particulier pour le système Material Design et la bibliothèque Compose Material, mais aussi pour d'autres systèmes de conception, nous disposons d'un composable MaterialTheme que vous appliquez tout en haut de la hiérarchie de l'UI sur votre écran. Vous pouvez également appliquer ce MaterialTheme en superposition sur n'importe quelle partie plus petite de votre UI.

  • Si vous regardez l'écran de droite, vous pouvez voir la carte "Play Points Gold" en haut, qui est une petite carte avec un indicateur de progression et quelques textes.

  • Nous appliquons cette superposition Material Theme avec un jeu de couleurs personnalisé généré par la bibliothèque Material Color Utilities, disponible sur GitHub.

  • Nous transmettons une couleur de base de type jaune/marron/or, et l'outil génère le spectre complet des jetons de couleur Material (couleur principale sur couleur principale, couleur secondaire sur couleur secondaire, etc.) que nous utilisons ensuite dans l'implémentation de cette fiche.

  • Cela permet aux développeurs Android de profiter de toutes les fonctionnalités de thématisation dynamique.

  • Tout est fait dans le code, tout est fait en Kotlin, ce qui signifie qu'il est beaucoup plus facile de créer le modèle mental approprié de son fonctionnement et qu'il est beaucoup plus facile de déboguer.

  • En interne, ces superpositions sont associées en tant que CompositionLocals aux nœuds d'interface utilisateur spécifiques de votre hiérarchie, là où vous choisissez de les appliquer.

  • Considérations sur les performances : la génération d'un jeu de couleurs complet avec la bibliothèque Material Color Utilities n'est pas sans frais.

  • Cela entraîne une certaine surcharge.

  • Si vous avez un élément suffisamment complexe qui nécessite plusieurs de ces composants, comme une boîte bento ou autre, selon les besoins de votre produit, et que vous générez plusieurs jeux de couleurs au moment de l'exécution, cela commence à s'accumuler, ce qui augmente la latence et les à-coups.

  • Vous devez donc, d'une part, commencer à mesurer l'impact sur vos performances et, d'autre part, décharger une partie de cette surcharge de l'exécution vers la compilation.

  • Vous pouvez utiliser la même bibliothèque Material Color Utilities au moment de la compilation pour prégénérer ces jeux de couleurs en fonction de vos besoins de branding ou de produit, et décharger cette surcharge au moment de la compilation.

  • Les CompositionLocals que j'ai mentionnés et qui permettent de suivre l'emplacement exact des superpositions dans l'arborescence de la hiérarchie de l'UI sont beaucoup moins coûteux, mais pas sans frais.

  • Donc, selon le nombre de ces éléments que vous utilisez, des dizaines, des centaines, cela commence à s'accumuler.

  • À un moment donné, vous devrez commencer à examiner le coût de tous ces CompositionLocals combinés.

  • Voici un exemple de ce que j'évoquais, à savoir les véritables fonctionnalités de thématisation dynamique de Compose au moment de l'exécution.

  • Ici, nous avons quatre quadrants, les mêmes visuels, la même carte d'événement.

  • Nous avons cette image héros qui s'étend sur toute la fiche, puis un libellé en haut à gauche, un bouton en bas à droite et quelques textes.

  • À droite de chaque quadrant, vous pouvez voir les jetons de couleur utilisés comme spécification de conception pour chacun des éléments.

  • L'implémentation de la carte est exactement la même pour ces quatre éléments.

  • La seule différence est que la superposition de la thématisation Material qui encapsule la fiche est générée ou configurée avec un jeu de couleurs créé de manière dynamique en fonction de la couleur dominante de l'image : bleu, violet, jaune et rouge.

  • Tout le reste reste inchangé.

  • Vous n'avez pas besoin de détruire et de recréer votre activité.

  • Vous pouvez l'appliquer de manière conditionnelle en fonction de vos flags d'expérimentation ou de tout autre besoin métier.

  • Comme je l'ai déjà dit, il s'agit d'un monde beaucoup plus dynamique, véritablement dynamique, pour appliquer des personnalisations de couleur à votre application.

  • Je laisse maintenant la parole à Jon pour la section suivante.

Fiabilité et vitesse du scaling

  • Oui.

  • C'est un autre exemple de la flexibilité dont parlait Kirill.

  • Parlons de la fiabilité et de la vélocité.

  • Tous les développeurs et toutes les entreprises cherchent donc à créer rapidement du code de haute qualité.

  • Voyons comment Compose a permis à Play d'y parvenir.

  • Tout d'abord, je sais que ce diagramme est complexe, mais la simplicité de l'architecture présente d'énormes avantages pour tous les auteurs et responsables de la maintenance du code, qu'il s'agisse d'humains ou d'agents.

  • Je ne vais pas trop m'étendre sur le sujet, mais l'un des modèles mentaux que Compose essaie de mettre en place concerne le flux de données unidirectionnel, et cela a vraiment eu un impact important sur notre équipe.

  • Pour ceux qui ne connaissent pas son fonctionnement, le principe de base est que vous disposez d'une source de données.

  • Une source de données fournit des données.

  • Ces données peuvent être transformées en une UI spécifique, que nous générons en tant que modèle d'UI.

  • Compose peut ensuite l'observer facilement en appelant simplement une propriété de valeur sur cet état.

  • C'est ce que représentent les flèches en haut de ce diagramme.

  • Les événements circulent dans le sens inverse.

  • Ainsi, si un utilisateur clique sur un bouton, l'action est renvoyée au transformateur d'UI, qui met à jour la source de données, émet une nouvelle valeur et exécute les transformations. Et la boucle se répète.

  • Tout passe donc par cette boucle relativement simple.

  • Nous avons constaté que cela permettait de réduire la période d'apprentissage.

  • Vous n'avez plus à vous demander où se produisent tous ces appels au thread principal ou à partir de ces autres threads.

  • Il suit une boucle générale.

  • Compose facilite l'observation des données, et les données bénéficient de garanties de cohérence forte entre les couches architecturales.

  • Le modèle mental a réduit de nombreuses conversations sur les sources de vérité au sein de notre équipe et a complètement éliminé plusieurs types de conditions de concurrence.

  • Un autre avantage considérable par rapport à notre ancienne architecture modèle-vue-contrôleur est qu'il est devenu très simple d'exécuter en parallèle des sources de données et des transformations d'UI.

  • Cela a vraiment amélioré notre latence de chargement dans le Store, de plusieurs dizaines de millisecondes, environ 50 ms.

  • C'était assez impressionnant pour nous.

  • Associé au flux de données unidirectionnel, l'autre grand avantage de Compose est l'interface utilisateur déclarative.

  • Kirill en a un peu parlé.

  • Les développeurs Play ont donc vraiment apprécié cette fonctionnalité.

  • Le flux de contrôle de l'interface utilisateur se trouve désormais dans un seul fichier.

  • L'exemple à droite est assez simple.

    @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)
        }
      }
    }
  • Nous passons d'une implémentation de bouton à une autre en fonction d'un flag de test.

  • Au lieu de devoir lire plusieurs fichiers de vue, ou des fichiers de fragment et des fichiers XML, il vous suffit de lire de haut en bas, ce qui simplifie grandement les choses.

  • Le coût de l'imbrication des composables est également bien inférieur à celui des hiérarchies de vues imbriquées. Cela nous a permis d'organiser naturellement notre code pour le rendre plus lisible, au lieu de devoir l'optimiser au maximum pour améliorer les performances.

  • Nous avons également constaté que les rappels de cycle de vie sont beaucoup plus simples et que leur nombre a été réduit.

  • Ainsi, au lieu d'avoir un cycle de vie de vue, un cycle de vie de fragment et un cycle de vie d'activité, vous obtenez un effet jetable, un effet secondaire et, selon l'endroit où vous le placez, il agit de manière très cohérente.

  • Cela nous a donc énormément aidés.

Présentation des LLM

  • À mon avis, ces deux changements architecturaux ont vraiment ouvert la voie aux LLM et leur ont permis de générer du code d'assez bonne qualité.

  • Je suis sûr que beaucoup d'entre vous ont déjà essayé ou fait cela avec leur LLM préféré.

  • Vous pouvez prendre une capture d'écran annotée avec des couleurs et une typographie, et l'envoyer au modèle. Il peut générer des lignes, des colonnes, du texte et des boutons, et il s'en sort plutôt bien.

  • Toutefois, elle présente certaines limites.

  • Et ce que Play a vraiment vu, c'est qu'il ne comprend pas votre codebase, n'est-ce pas ?

  • Il ne sait pas quels composants vous avez déjà créés et qu'il devrait réutiliser, ni quels sont les noms des jetons de conception.

  • Il vous fournit simplement des couleurs et des chaînes codées en dur.

  • Quel contenu doit provenir de l'appareil ? Quel contenu doit provenir d'un serveur ? Comment m'assurer que l'utilisation de LazyList est efficace et ne crée pas simplement une colonne énorme ?

  • Pour résoudre certains de ces problèmes, nous avons annoté ces captures d'écran avec un peu plus de métadonnées.

  • Nous avons donc besoin des noms des éléments d'UI, des cadres de délimitation pour savoir où les composants commencent et se terminent, des jetons de conception pour les noms sémantiques des couleurs et de la typographie, des compétences, ainsi que de quelques prompts pour indiquer où l'élément sera placé afin de prendre en compte ces considérations de performances.

  • et une signature de fonction de très haut niveau, afin de pouvoir lui indiquer quel contenu est dynamique et quel contenu est statique.

  • Vous obtenez ainsi un résultat similaire à ce que nous avions avant, en passant à l'après.

  • Je n'ai pas inclus les cadres de délimitation ici, car cela ajouterait beaucoup de bruit au diagramme.

  • Mais vous pouvez voir que ces couleurs et noms de typographie codés en dur sont remplacés par "title large" et "on surface".

  • Les noms des composants, tels que l'en-tête de la fiche et le badge d'icône, sont clairement indiqués.

  • Ainsi, ils seront disponibles dans votre codebase.

  • Pour nous, beaucoup d'entre eux proviennent de bibliothèques de conception courantes, dont Kirill parlera dans un instant.

  • Vous n'avez donc pas besoin d'étiqueter manuellement toutes ces données à chaque fois.

  • Vous associez cela à une signature de méthode comme celle que nous avons en bas, OfferCard, et il sait alors que le titre, le endDate et l'image sont tous dynamiques.

  • Nous ne devons pas les coder en dur.

  • En plus de ces noms sémantiques, nous pouvons désormais passer à toutes les différentes applications de couleur dont Kirill parlait.

  • Nous générons ainsi beaucoup plus de code.

  • Je vais maintenant laisser la parole à Kirill, qui va vous expliquer comment nous maintenons la qualité.

Automatisation de la qualité

  • C'est vrai.

  • Merci, Jon.

  • Pour continuer sur le thème du développement assisté par LLM et par agent, nous allons d'abord nous intéresser à la conception de l'expérience utilisateur.

  • Quel que soit l'outil de conception que vous choisissez (Figma ou autre), vous devez disposer d'un modèle partagé utilisé par tous les concepteurs, qui contient des jetons de couleur, de typographie et de forme provenant du système de conception de votre choix.

  • Peut-être que c'est Material.

  • Il s'agit peut-être de votre système de conception personnalisé.

  • Et vous souhaitez que les jetons de couleur de ces modèles soient compatibles de manière intégrée avec le passage du mode clair au mode sombre, et du mode de contraste normal au mode de contraste moyen ou élevé, introduits au niveau d'Android il y a quelques années.

  • Les concepteurs peuvent ainsi passer rapidement d'une combinaison à l'autre pour voir comment leurs spécifications de conception réagissent.

  • Ensuite, lorsqu'il est finalisé et transmis à l'équipe d'implémentation, dans ce pipeline d'exportation, vous devez pouvoir vérifier que chaque couleur, chaque élément typographique et chaque forme utilise un jeton correspondant au lieu d'une valeur RVB, d'une famille de polices ou d'une taille de police codées en dur.

  • Enfin, ce que nous avons trouvé très utile à l'échelle de Google Play, c'est que nous avons non pas des dizaines, mais des centaines de composants, de clusters, de fiches et de conteneurs qui sont utilisés sur différents écrans.

  • Nous avons trouvé utile de regrouper toutes ces informations dans un seul endroit, que nous appelons un catalogue de composants, puis d'entraîner un agent personnalisé sur ce catalogue.

  • C'est particulièrement utile lorsque vous commencez un nouvel écran, un nouveau parcours utilisateur ou une nouvelle zone de produit. À partir de ces premières explorations de conception, qu'il s'agisse de diapositives ou de spécifications Figma, vous pouvez alimenter l'agent, qui vous aidera à identifier rapidement les composants existants. Vous n'avez donc pas besoin de les reconcevoir, de les respécifier ni de les réimplémenter de zéro.

  • Cela réduit considérablement les coûts de conception et de mise en œuvre.

  • Pour l'implémentation, nous nous appuyons fortement sur les règles Lint de base et personnalisées.

  • Je souhaite attirer votre attention sur deux règles Lint principales : FrequentlyChangingValueDetector, qui permet d'identifier les sources de recompositions inutiles pouvant entraîner une latence et des à-coups, et ScaffoldPaddingDetector, qui permet de signaler les cas où nous utilisons le composable Scaffold de Material Compose, mais ignorons les marges intérieures entrantes.

  • Ce n'est pas une source de latence ni de saccades, mais, dans certains cas, cela peut entraîner des problèmes très difficiles à déboguer, comme des défauts d'alignement de la mise en page dans certains cas, par exemple, lorsque l'affichage est bord à bord, ou lors du pliage ou du dépliage.

  • Enfin, BoxWithConstraints présente certaines considérations de performances.

  • Deux frames peuvent être nécessaires pour tout disposer correctement.

  • Nous ne le bloquons pas complètement, mais nous le signalons comme un avertissement Lint afin que le développeur qui travaille sur cet écran sache qu'il fait un choix spécifique en utilisant BoxWithConstraints, ou qu'il peut choisir d'utiliser autre chose pour cette mise en page spécifique.

  • Pour l'automatisation des thèmes, nous avons de nouveau des jetons de couleur, de typographie et de forme.

  • Nous avons une règle Lint qui bloque l'utilisation de couleurs et de typographies codées en dur.

  • Nous avons une règle Lint qui signale l'utilisation de composants Material 2.

  • Nous ne voulons utiliser que Material 3, la version la plus récente et la plus performante, y compris les nouveaux composants expressifs introduits l'année dernière et cette année.

  • Nous avons une règle Lint personnalisée qui empêche les utilisateurs de lire les couleurs à partir de fichiers XML anciens, par exemple.

  • Nous voulons utiliser Compose en priorité et exclusivement pour les nouveaux écrans.

  • De plus, les composables Text, en particulier dans le système de conception Material Design, disposent de solutions de remplacement pour le style et la couleur.

  • Ils les lisent à partir de la couleur du contenu local et de la typographie locale, mais nous ne voulons pas nous fier à cela.

  • Nous voulons que chaque texte utilise intentionnellement le style, le style de typographie et la couleur spécifiques de la spécification de conception.

  • C'est une règle d'analyse lint que nous avons.

  • Enfin, dans la même veine que ScaffoldPaddingDetector, nous avons une règle Lint personnalisée qui impose que chaque fonction composable utilise son modificateur d'entrée.

  • Encore une fois, pour éviter que, vous savez, de nouvelles utilisations soient mal placées, ou ne respectent pas l'arrière-plan entrant, ou quoi que ce soit d'autre.

Conclusion

  • Voici les trois points principaux que nous aimerions que vous reteniez de cette présentation.

  • Tout d'abord, aujourd'hui, fin 2026, nous pensons que Compose est un kit d'interface utilisateur mature, qui a fait ses preuves à grande échelle.

  • Android lui-même est conçu pour Compose.

  • Plus tôt cette année, lors de Google I/O, nous avons annoncé que toutes les bibliothèques d'UI et tous les flux d'agents étaient conçus en priorité pour Compose.

  • Comme Jon l'a mentionné plus tôt dans la présentation, nous vous suggérons de migrer progressivement, en particulier les codebases volumineux, pour accélérer votre vélocité pour les flux de développeurs et les flux d'agents.

  • Nous vous remercions de nous avoir accordé de votre temps aujourd'hui. Dans quelques minutes, Jon et moi serons à l'extérieur pour répondre à vos questions.

  • Merci encore pour le temps que vous m'avez accordé.

Code

Extraits de code

Extrait de code Kotlin à 16:09 dans "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)
    }
  }
}