Nozioni di base sulle app

Migrazione di vent'anni di app Google Play a Jetpack Compose

Altoparlanti

  • Kirill Grouchnikov

    Software engineer

  • Jon Boekenoogen

    Software Engineer

Informazioni

Informazioni sulla presentazione

Quest'anno, Android è diventato ufficialmente Compose-first per la creazione di tutte le UI, mettendo le visualizzazioni legacy in modalità di manutenzione. Per Google Play, questo percorso è iniziato nel 2020. In un'esperienza di progettazione che dura da quasi vent'anni e che coinvolge miliardi di utenti, la migrazione a Jetpack Compose è stata ottenuta grazie a best practice collaudate, alla stretta collaborazione con il team principale di Compose e alla continua evoluzione degli strumenti.

Scopri come la modernizzazione di Google Play con Compose ha portato a miglioramenti misurabili in termini di velocità e stabilità a lungo termine. La sessione illustra come collegare i flussi di lavoro di progettazione di Figma basati su agenti con l'implementazione di Compose, automatizzando la qualità per evitare ricomposizioni non necessarie e creando interfacce espressive con colori dinamici, tipografia avanzata e forme stratificate. Scoprirai strategie collaudate per classificare i bug più velocemente e scalare la tua migrazione a Compose in tutta sicurezza.

Riepilogo

  • Google Play ha spostato il 97% delle impressioni degli utenti su schermate solo Compose nell'arco di sei anni. Inoltre, negli ultimi 14 mesi, le pagine principali hanno registrato un miglioramento del 30% del tasso di jank.
  • L'adozione incrementale riduce i rischi aziendali in codebase di grandi dimensioni. I team possono acquisire familiarità prima con le schermate a basso traffico, per poi passare all'hosting di ComposeView direttamente nella radice dell'attività.
  • I temi dinamici funzionano interamente nel codice utilizzando gli overlay MaterialTheme e la libreria Material Color Utilities. In questo modo si evitano le interruzioni delle attività, anche se la generazione di combinazioni di colori in fase di build aiuta a limitare la latenza di runtime.
  • Il flusso di dati unidirezionale e l'interfaccia utente dichiarativa semplificano l'architettura e rimuovono diversi tipi di race condition. L'esecuzione in parallelo delle origini dati e delle trasformazioni dell'interfaccia utente ha migliorato la latenza di caricamento di Google Play di decine di millisecondi.
  • I controlli Lint automatici applicano le regole del sistema di progettazione e della qualità del codice. Play li utilizza per bloccare i colori impostati come hardcoded e segnalare potenziali problemi di prestazioni, come BoxWithConstraints.

Gemini Notebook

Argomenti

  • jetpack-compose
  • migrazione
  • prestazioni
  • tematizzazione
  • unidirectional-data-flow
  • lint-rules
  • developer-velocity

Trascrizione

Scarica la trascrizione

Introduzione e adozione del Google Play Store

  • Ciao a tutti!

  • Mi chiamo Jon.

  • Sono un membro del team di Google Play Store.

  • Questo è il mio collega Kirill.

  • Oggi siamo qui per parlarvi di come abbiamo trasferito molto codice dal sistema View e Fragment a Compose.

  • Iniziamo.

  • Quindi, com'è andata l'adozione e qual è stata la sua portata?

  • Il codebase della nostra app è cresciuto in modo organico dal 2007 circa.

  • Abbiamo oltre un milione di righe di codice di produzione, 200 schermate e 500 componenti UI unici utilizzati in molte di queste schermate.

  • Nel 2020, abbiamo deciso che la velocità, l'affidabilità e le prestazioni degli sviluppatori non stavano raggiungendo gli obiettivi che volevamo.

  • Abbiamo quindi deciso di adottare uno stack tecnologico per l'interfaccia utente moderno.

  • Abbiamo valutato diverse librerie.

  • Inoltre, alcuni amici di AndroidX ci hanno parlato di Compose in quel periodo e abbiamo deciso di adottarlo e diventare il primo partner importante di Compose.

  • Com'è andata?

  • Sei anni dopo, il 97% delle impressioni degli utenti nell'app Play Store avviene su schermate solo Compose.

  • Tutto, scusa, tutto lo sviluppo per smartphone e schermi di grandi dimensioni è passato solo a Compose dal 2020.

  • Anche i nostri fattori di forma estesi, XR, TV, Auto, Wear, sono passati a Compose dal 2025.

  • Compose ha contribuito in modo significativo a questo successo e al motivo per cui abbiamo continuato ad adottarlo sempre di più.

  • Hanno una suite di test molto solida e completa che ci ha aiutato ad adottare nuove versioni di Compose due volte alla settimana.

  • L'integrazione delle build alpha e delle nuove API ci aiuta a sfruttare le nuove correzioni di bug, i nuovi miglioramenti delle prestazioni e a esplorare alcune di queste nuove API e offrire nuove esperienze utente.

  • In particolare, per quanto riguarda le prestazioni, Compose ha davvero offerto prestazioni costanti per la nostra app in tutte le schermate principali.

  • Si tratta della pagina dei risultati di ricerca, della home page e della pagina dei dettagli.

  • Queste metriche (prestazioni, jank e latenza di caricamento) sono molto importanti per la nostra attività e anche per l'esperienza utente.

  • Abbiamo quindi registrato un miglioramento del 30% negli ultimi 14 mesi.

Piano di migrazione

  • Ma come siamo arrivati a questo punto?

  • È proprio di questo che vogliamo parlare.

  • Parliamo quindi del piano di migrazione.

  • Per questo motivo, Google Play ha adottato un approccio in più fasi.

  • Non volevamo buttarci a capofitto e mettere tutte le uova nello stesso paniere, per così dire.

  • Abbiamo finito per adottare alcune misure per comprendere i rischi, l'impatto sulla nostra attività e acquisire fiducia prima di impegnarci completamente.

  • Quindi, li chiamerò: gattonare, camminare, fare jogging e correre.

  • Quindi, per noi, la fase di gattonamento è stata un modo per acquisire familiarità con Compose.

  • Abbiamo iniziato con una pagina con traffico ridotto.

  • Potrebbe essere la pagina delle impostazioni, le licenze di terze parti e così via.

  • Il tuo obiettivo principale è acquisire familiarità con la libreria Compose.

  • In questo modo, puoi abituarti a righe, colonne, testo, immagini e così via.

  • Poi devi iniziare a portare con te tutta l'infrastruttura dell'app e capire come funziona in Compose.

  • Quindi, potrebbe trattarsi di logging delle impressioni, logging dei clic, temi, stavamo rinnovando il caricamento dei dati allo stesso tempo.

  • Quindi un po' tutte queste cose.

  • Una cosa in particolare che abbiamo trovato utile è stata garantire che tutte le nostre schermate avessero un aspetto coerente. Abbiamo creato alcuni test delle unità e test funzionali per verificare che i nostri oggetti di tematizzazione in Compose fossero mappati direttamente agli stili XML, alla tipografia, ai colori e a tutti questi elementi.

  • Una volta acquisita un po' di familiarità e dopo aver preso confidenza, abbiamo deciso di passare alla camminata.

  • Per noi, questo ha significato prendere un componente più piccolo su una schermata con un traffico molto elevato e valutare l'aspetto di questo tipo di migrazione.

  • Ti consigliamo di prendere un elemento che si trova in una RecyclerView, in modo da comprendere eventuali problemi di compatibilità tra la View e il sistema Compose, nonché di misurare le prestazioni e il jank lungo il percorso.

  • Il componente in sé non deve essere super complesso, ma è importante avere qualcosa che metta alla prova i layout, come testo, immagini e così via, un paio di istanze diverse di ciò che vedresti normalmente.

  • Un aspetto da tenere d'occhio e probabilmente da aspettarsi in quest'area è un certo aumento di jank e latenza, che sarà lieve, ma ciò è dovuto al fatto che ora stai eseguendo due stack.

  • Hai uno stack di rendering interamente in Compose e uno in Views.

  • Quindi ci sarà un po' di thrashing della memoria, un po' di caricamento di classi aggiuntive e così via.

  • Tuttavia, man mano che adotti Compose, questo problema scomparirà.

  • Se ne hai davvero bisogno nel frattempo, puoi eseguire un leggero preriscaldamento di quella schermata per allinearla e mitigare il costo nel breve termine.

  • Quindi, dopo la camminata, passiamo al jogging.

  • Questo è il caso in cui abbiamo acquisito molta familiarità con il sistema.

  • Anziché un singolo componente su una pagina ad alto traffico, esegui il test sull'intera pagina ad alto traffico.

  • In questo caso, abbiamo mantenuto la libreria di navigazione e l'utilizzo dei frammenti, ma ogni singola schermata è stata implementata completamente in Compose.

  • Abbiamo appena fatto in modo che il frammento restituisca la stessa ComposeView.

  • Quindi, puoi aspettarti una latenza e un jank migliorati.

  • Non si verificano i problemi di thrashing della memoria e caricamento delle classi di cui parlavo.

  • Inoltre, Compose esegue anche alcuni livelli di memorizzazione nella cache a livello di ComposeView.

  • Quindi, se hai una RecyclerView con un gruppo di schede che hanno un aspetto coerente e potrebbero avere le stesse icone, l'analisi delle icone e l'utilizzo delle risorse sono condivisi tra tutti gli elementi di ComposeView.

  • Quindi, siamo passati alla corsa.

  • Questo è il momento di dare il massimo.

  • Una volta che la maggior parte del traffico della tua app proviene da Compose, passiamo al livello successivo.

  • Sopra le schermate, abbiamo Attività.

  • Quindi, sposta ComposeView nella radice dell'attività.

  • Inoltre, gran parte del codice sarà relativamente simile.

  • Stai ancora cercando di eseguire un'istruzione di navigazione, ad esempio passare da una schermata all'altra.

  • Ma invece di eseguire transazioni di frammenti, chiami una funzione componibile.

  • Puoi farlo con la libreria Nav2 o Nav3, a seconda di quella che scegli.

  • Nel nostro caso, non avevamo eseguito la migrazione di tutte le schermate.

  • Ho già detto che ne abbiamo molti.

  • Per questo motivo, abbiamo creato la compatibilità con i frammenti, in modo che tu possa avere una schermata basata su frammenti e sfruttare i wrapper AndroidFragment di Compose per farlo.

  • Cosa puoi aspettarti? Ancora una volta, i problemi di jank e latenza sono importanti per la nostra attività, quindi continuiamo a spingerci oltre i limiti e continuerai a vedere miglioramenti, perché ora abbiamo la memorizzazione nella cache tra le schermate e molti meno problemi di thrashing della memoria.

  • Ma ottieni anche nuove funzionalità.

  • Un esempio è mostrato a destra in questa GIF, dove puoi eseguire transizioni di elementi condivisi tra le schermate.

  • Quindi abbiamo un'immagine che ingrandiamo quando passi da una schermata all'altra e questo fornisce continuità.

  • Puoi anche sfruttare tutta la flessibilità delle animazioni di Compose durante l'intera transizione.

  • A questo punto, passo la parola a Kirill, che parlerà di altre funzionalità.

Temi e prestazioni

  • Grazie, Jon.

  • Vorrei parlare un po' di un argomento che mi sta molto a cuore, ovvero i temi e gli stili per le app per Android, un'attività che svolgo da un po' di tempo.

  • Nel mondo delle visualizzazioni, c'era il codice Java e, poco dopo, il codice Kotlin, poi c'erano le risorse XML, come colori, stringhe, dimensioni, layout, temi e stili.

  • In pratica, tutte queste risorse XML venivano compilate in una tabella di risorse inclusa nell'APK, che era praticamente statica.

  • Esisteva un'API Resources.Theme.applyStyle che potevi utilizzare dinamicamente in fase di runtime per applicare uno stile personalizzato alla gerarchia della UI.

  • La limitazione principale era o è che devi farlo prima di eseguire l'inflate dei contenuti, il che significa che se vuoi applicare dinamicamente questo stile a un elemento esistente della UI, devi eliminare e ricreare l'intera attività, il che non è il massimo per l'esperienza utente.

  • Inoltre, poiché applicava questi blocchi XML precompilati, stava diventando un po' difficile combinare più overlay dinamici condizionali uno sopra l'altro in base ai flag dell'esperimento o ad altre esigenze aziendali.

  • Era un po' difficile creare un modello mentale adeguato della gerarchia degli stili in quel mondo XML.

  • Infine, non esisteva una singola visualizzazione unificata in Android Studio o in qualsiasi altro strumento per sviluppatori che consentisse di colmare il divario tra il mondo Java, il mondo del codice e il mondo XML.

  • Era un po' difficile destreggiarsi e creare il modello mentale corretto ed eseguire il debug del motivo per cui il mio stile non veniva applicato, perché ottenevo il colore sbagliato e così via.

  • Nel nuovo mondo, nel mondo di Compose, in particolare per il sistema Material Design e la libreria Compose Material, ma anche per altri sistemi di progettazione, per il sistema Material Design abbiamo un MaterialTheme componibile che applichi nella parte superiore della gerarchia della UI sullo schermo e puoi anche applicare questo MaterialTheme come overlay su qualsiasi parte più piccola della UI.

  • Se guardi lo schermo a destra, puoi vedere il livello Oro di Play Points in alto, che è una piccola scheda con l'indicatore di avanzamento e un paio di testi.

  • Applichiamo questo overlay di temi di Material con una combinazione di colori personalizzata generata dalla libreria Material Color Utilities, disponibile su GitHub per l'utilizzo.

  • Passiamo una sorta di colore marrone, giallo, oro come seme e generiamo l'intero spettro di token di colore Material, primario su primario, secondario su secondario, che poi utilizziamo nell'implementazione di questa scheda.

  • In questo modo, gli sviluppatori Android hanno a disposizione la funzionalità completa di temi dinamici.

  • Tutto viene eseguito nel codice, tutto viene eseguito in Kotlin, il che significa che è molto più facile creare il modello mentale corretto di come funziona il tutto ed è molto più facile eseguire il debug.

  • Internamente, questi overlay vengono collegati come CompositionLocal ai nodi UI specifici della gerarchia in cui scegli di applicarli.

  • Considerazioni sul rendimento: la generazione di una combinazione di colori completa con la libreria Material Color Utilities non è senza costi.

  • Comporta un certo overhead.

  • Quindi, se hai qualcosa di abbastanza complicato che richiede più elementi di questo tipo, una sorta di bento box o qualsiasi altra cosa, a seconda delle esigenze del tuo prodotto, e hai più combinazioni di colori che generi in fase di runtime, questo inizia ad accumularsi, inizia ad aumentare la latenza e il jank.

  • Quindi, a, vuoi iniziare a misurare l'impatto sulle prestazioni e b, puoi scaricare parte di questo overhead dal runtime al tempo di build.

  • Puoi utilizzare la stessa libreria Material Color Utilities in fase di build per pregenerare queste combinazioni di colori in base alle tue esigenze di branding o di prodotto e trasferire questo overhead a una fase di build.

  • Per quanto riguarda i CompositionLocal che ho menzionato, che tengono traccia della posizione esatta degli overlay nell'albero della gerarchia della UI, sono molto più economici, ma non sono comunque senza costi.

  • Quindi, a seconda di quanti ne utilizzi, decine, centinaia, il costo inizia ad aumentare.

  • A un certo punto, è necessario iniziare a esaminare il costo di tutti questi elementi locali di composizione combinati.

  • Questo è un esempio di ciò che ho menzionato, ovvero le funzionalità di tematizzazione dinamica in fase di runtime di Compose.

  • Qui abbiamo quattro quadranti, gli stessi elementi visivi, la stessa, chiamiamola, scheda evento.

  • Abbiamo questa immagine hero che occupa l'intera scheda, poi un'etichetta in alto a sinistra, un pulsante in basso a destra e un paio di testi.

  • Sul lato destro di ogni quadrante, puoi vedere i token di colore utilizzati come specifica di progettazione per ciascuno degli elementi.

  • L'implementazione della scheda è esattamente la stessa per tutti e quattro i tipi.

  • L'unica differenza è che l'overlay del tema di Material che racchiude la scheda viene generato o configurato con una combinazione di colori creata dinamicamente in base al colore dominante dell'immagine: blu, viola, giallo e rosso.

  • Tutto il resto rimane invariato.

  • Non è necessario eliminare e ricreare l'attività.

  • Puoi applicarlo in modo condizionale in base ai flag dell'esperimento o ad altre esigenze aziendali.

  • E, come ho già detto, è un mondo molto più dinamico, davvero dinamico, per l'applicazione di personalizzazioni dei colori alla tua app.

  • Ora ripasso la parola a Jon per la prossima sezione.

Scalabilità dell'affidabilità e della velocità

  • Sì.

  • Quindi, questa è un'ulteriore flessibilità di cui parlava Kirill.

  • Parliamo di affidabilità e velocità.

  • Pertanto, la creazione rapida di codice di alta qualità è un obiettivo che tutti gli sviluppatori e le aziende cercano di raggiungere.

  • Vediamo come Compose ha aiutato Play a farlo.

  • Quindi, prima di tutto, so che è un diagramma grande, ma la semplicità dell'architettura offre enormi vantaggi per tutti gli autori e i gestori del codice, sia umani che agenti.

  • Non voglio approfondire troppo questo aspetto, ma uno dei modelli mentali che Compose cerca di proporre riguarda il flusso di dati unidirezionale, che ha avuto un grande impatto sul nostro team.

  • Per chi non ha familiarità con il suo funzionamento, le nozioni di base sono che hai un'origine dati.

  • Un'origine dati fornisce i dati.

  • Questi dati potrebbero essere trasformati in una UI specifica, che viene restituita come modello di UI.

  • Compose può quindi osservarlo facilmente chiamando una proprietà value su quello stato.

  • Questo è un po' il significato delle frecce lungo il lato superiore di questo diagramma.

  • Poi gli eventi fluiscono nella direzione opposta.

  • Quindi, se un utente fa clic su un pulsante, questo torna al trasformatore UI, aggiorna l'origine dati, emette un nuovo valore, esegue le trasformazioni e si ottiene questo loop.

  • Quindi tutto viene eseguito attraverso questo loop relativamente semplice.

  • I vantaggi che abbiamo riscontrato sono la riduzione del periodo di adattamento.

  • Non è più necessario chiedersi dove avvengono tutte queste chiamate al thread principale o ad altri thread.

  • Segue un percorso ad anello generale.

  • Compose semplifica l'osservazione dei dati e garantisce un'elevata coerenza dei dati tra i livelli dell'architettura.

  • Il modello mentale ha ridotto molte conversazioni sulle fonti di attendibilità all'interno del nostro team e ha rimosso completamente diversi tipi di race condition.

  • Un altro enorme vantaggio per noi è che, rispetto alla nostra precedente architettura model-view-controller, è diventato molto, molto semplice eseguire in parallelo le origini dati e le trasformazioni della UI.

  • Questo ha migliorato notevolmente la latenza di caricamento all'interno dello Store, di decine di millisecondi, circa 50 ms.

  • È stato davvero impressionante per noi.

  • Oltre al flusso di dati unidirezionale, l'altro grande vantaggio di Compose riguarda l'UI dichiarativa.

  • Kirill ne ha parlato un po'.

  • Anche gli sviluppatori di Google Play hanno apprezzato molto questa funzionalità.

  • Il flusso di controllo UI è ora in un unico file.

  • Sulla destra vediamo un esempio abbastanza semplice.

    @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)
        }
      }
    }
  • Stiamo passando da un'implementazione dei pulsanti all'altra in base a un flag dell'esperimento.

  • Invece di dover leggere più file di visualizzazione o, ad esempio, file di frammenti e file XML, basta leggerli dall'alto verso il basso ed è molto più semplice.

  • Inoltre, il costo della nidificazione dei componibili è molto più basso rispetto alle gerarchie di oggetti View nidificate e ci ha permesso di organizzare il nostro codice in modo naturale per renderlo più leggibile, invece di dover spremere ogni minimo dettaglio per migliorare le prestazioni.

  • Altri vantaggi che abbiamo riscontrato sono i callback del ciclo di vita, che sono stati molto più semplici e sono stati ridotti nel numero di quelli di cui devi preoccuparti.

  • Quindi, invece di avere il ciclo di vita della visualizzazione, il ciclo di vita del frammento, il ciclo di vita dell'attività, hai DisposableEffect, SideEffect e, a seconda di dove lo posizioni, agisce in modo molto coerente.

  • Questo è stato un enorme vantaggio per noi.

Preparazione per gli LLM

  • Quindi, secondo me, queste due modifiche architetturali hanno davvero preparato il terreno per gli LLM e hanno consentito loro di generare codice di qualità piuttosto elevata.

  • Sono sicuro che molti di voi hanno provato o fatto questo con il loro LLM preferito.

  • Potresti acquisire uno screenshot con annotazioni di colori e tipografia e inserirlo per vedere se è in grado di generare righe, colonne, testo e pulsanti, e fa un lavoro ragionevole.

  • Tuttavia, presenta alcune limitazioni.

  • E ciò che Play ha effettivamente riscontrato è che non comprende il tuo codebase, giusto?

  • Non sa quali componenti hai già creato e che dovrebbero essere riutilizzati, non conosce i nomi dei token di progettazione.

  • Ti fornisce solo colori e stringhe hardcoded.

  • Quali contenuti devono provenire dal dispositivo, quali da un server o come faccio ad assicurarmi che l'utilizzo di LazyList sia efficiente e non crei solo una colonna enorme?

  • Per risolvere alcuni di questi problemi, abbiamo annotato gli screenshot con un po' più di metadati.

  • Quindi, nomi dell'interfaccia utente, riquadri di delimitazione per sapere dove iniziano e finiscono i componenti, token di progettazione per i nomi semantici di colori e tipografia, competenze e anche alcuni prompt per indicare dove verrà posizionato, in modo da poter tenere conto di queste considerazioni sulle prestazioni.

  • Inoltre, una firma della funzione di altissimo livello, in modo da poter indicare quali contenuti sono dinamici e quali statici.

  • Quindi, si ottiene qualcosa di simile a quello che avevamo prima, passando al dopo.

  • Non ho inserito i riquadri di delimitazione qui perché aggiungerebbero molto rumore al diagramma.

  • Ma puoi vedere che i colori e i nomi dei caratteri tipografici hardcoded vengono sostituiti con title large e on surface.

  • I nomi dei componenti, come l'intestazione della scheda e il badge dell'icona, sono chiaramente contrassegnati.

  • In questo modo, possono essere trovati nel tuo codebase.

  • E per noi, molti di questi provengono anche da librerie di progettazione comuni, di cui Kirill parlerà tra un minuto.

  • Quindi, non devi etichettare tutti questi elementi ogni volta.

  • Se lo abbini a una firma del metodo come quella in basso, OfferCard, il sistema sa che il titolo, la endDate e l'immagine sono tutti dinamici.

  • Non dovremmo impostarli come hardcoded.

  • E insieme a questi nomi semantici, ora possiamo passare a tutte le diverse applicazioni di colore di cui parlava Kirill.

  • In questo modo, generiamo molto più codice.

  • Ora lascio la parola a Kirill, che vi parlerà di come sosteniamo la qualità.

Automazione della qualità

  • Infatti,

  • Grazie, Jon.

  • Quindi, continuando su questo argomento dello sviluppo assistito da agenti e LLM, iniziamo con il lato della progettazione UX.

  • Quello che devi fare è, qualunque sia il tuo strumento di progettazione preferito, magari Figma o qualcos'altro, avere un modello condiviso utilizzato da tutti i designer che contenga token di colore, token di tipografia e token di forma del tuo sistema di progettazione preferito.

  • Forse è Material.

  • Forse è il tuo sistema di progettazione personalizzato.

  • E, in particolare per i token di colore, vuoi che questi modelli abbiano un supporto integrato per passare dalla modalità Luce alla modalità Buio e per passare dalle modalità di contrasto Normale, Medio e Alto introdotte a livello di Android qualche anno fa.

  • In questo modo, i designer possono passare rapidamente da una combinazione all'altra per vedere come rispondono le loro specifiche di progettazione.

  • Poi, quando viene finalizzato e consegnato al team di implementazione, in quella pipeline di esportazione, vuoi avere una sorta di funzionalità per monitorare che ogni colore, ogni elemento tipografico, ogni forma utilizzi un token corrispondente invece di essere un valore RGB impostato come hardcoded o una famiglia di caratteri o una dimensione del carattere impostata come hardcoded.

  • Infine, ciò che abbiamo trovato molto utile su Google Play è che abbiamo non solo decine, ma alcune centinaia di componenti, cluster, schede e container che vengono utilizzati in una varietà di schermate.

  • Abbiamo trovato utile tenere traccia di tutto questo in un unico posto, che chiamiamo catalogo dei componenti, e poi addestrare un agente personalizzato su quel catalogo.

  • È utile quando inizi una nuova schermata, magari un nuovo percorso dell'utente, magari una nuova area di prodotto, e da quelle esplorazioni di progettazione iniziali, magari slide, magari specifiche di Figma, puoi inserirle nell'agente, che aiuta a identificare rapidamente quali componenti esistono già, in modo che non debbano essere riprogettati e rispecificati, quindi non debbano essere implementati di nuovo da zero.

  • In questo modo, i costi di progettazione e di implementazione si riducono notevolmente.

  • Per quanto riguarda l'implementazione, ci affidiamo molto alle regole Lint di base e personalizzate.

  • Un paio di regole Lint fondamentali che voglio segnalare sono FrequentlyChangingValueDetector, che aiuta a identificare le fonti di ricomposizioni non necessarie, che possono causare latenza e jank, e l'altra è ScaffoldPaddingDetector per segnalare i casi in cui utilizziamo il composable Scaffold di Material Compose, ma ignoriamo i padding in entrata.

  • Non è una fonte di latenza e jank, ma, in alcuni casi, può portare a disallineamenti del layout molto difficili da sottoporre a debug, ad esempio quando è edge-to-edge o quando si piega e si apre.

  • Infine, BoxWithConstraints comporta alcune considerazioni sulle prestazioni.

  • Potrebbero essere necessari due frame per disporre correttamente tutti gli elementi.

  • Non lo blocchiamo del tutto, ma lo contrassegniamo come avviso di Lint, in modo che lo sviluppatore che sta lavorando a quella particolare schermata sappia che sta facendo una scelta specifica per utilizzare BoxWithConstraints o forse può scegliere di utilizzare qualcos'altro per quel layout specifico.

  • Per l'automazione dei temi, ancora una volta, token di colore, token di tipografia, token di forma.

  • Abbiamo una regola Lint che blocca l'utilizzo di colori e tipografia impostati come hardcoded.

  • Abbiamo una regola Lint che segnala l'utilizzo dei componenti Material 2.

  • Vogliamo utilizzare solo Material 3, l'ultima e migliore versione, inclusi i nuovi componenti espressivi introdotti l'anno scorso e quest'anno.

  • Vogliamo Abbiamo una regola Lint personalizzata che impedisce alle persone di leggere i colori, ad esempio, dai file XML legacy.

  • Vogliamo utilizzare Compose come prima opzione e come unica opzione per le nuove schermate.

  • Inoltre, i componibili di testo, in particolare nel sistema Material Design, hanno dei fallback per lo stile e il colore.

  • Lo leggono dal colore dei contenuti locali e dalla tipografia locale, ma non vogliamo fare affidamento su questo.

  • Vogliamo che ogni singolo testo utilizzi intenzionalmente lo stile specifico, lo stile tipografico e il colore specifico delle specifiche di progettazione.

  • Questa è una regola di Lint che abbiamo.

  • Infine, sulla falsariga di ScaffoldPaddingDetector, abbiamo una regola Lint personalizzata che impone che ogni singola funzione componibile che abbiamo utilizzi il proprio modificatore di input.

  • Anche in questo caso, per evitare, ad esempio, che i nuovi utilizzi vengano posizionati in modo errato o non rispettino lo sfondo in arrivo o altro.

Conclusione

  • Questi sono i tre punti principali che vorremmo che tu traessi da questa presentazione.

  • La prima è che oggi, alla fine del 2026, secondo noi Compose è un toolkit UI maturo, collaudato su larga scala.

  • Android stesso è incentrato su Compose.

  • All'inizio di quest'anno, in occasione di Google I/O, abbiamo annunciato che tutte le librerie UI e tutti i flussi agentici sono Compose-first.

  • E, come ha detto Jon in precedenza nella presentazione, gattona, cammina, fai jogging e corri, ti suggeriamo di eseguire la migrazione in modo incrementale, soprattutto per codebase di grandi dimensioni, per accelerare la velocità dei flussi degli sviluppatori e degli agenti.

  • E con questo, vi ringraziamo per averci dedicato del tempo oggi. Tra qualche minuto, io e Jon saremo fuori per rispondere alle vostre domande.

  • Grazie ancora per il tempo che ci hai dedicato.

Codice

Snippet di codice

Snippet di Kotlin al minuto 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)
    }
  }
}