Postado por Andrew Flynn e Jon Boekenoogen, líderes técnicos do Google Play
Em 2020, a liderança de engenharia da Google Play Store tomou a importante decisão de reformular todo o conjunto de tecnologias de sua vitrine. O código existente tinha mais de dez anos de idade e estava muito ultrapassado, tecnicamente, em relação às inúmeras versões e atualizações de recursos da Plataforma Android. Precisávamos de novos frameworks que pudessem ser escalonados para as centenas de engenheiros que trabalham no produto sem impactar negativamente a produtividade dos desenvolvedores, a experiência do usuário ou o desempenho da loja em si.
Elaboramos um roteiro para vários anos para a atualização de todos os componentes da loja, desde a camada de rede até a renderização de pixels. Como parte disso, também queríamos adotar um framework de IU moderno e declarativo que atendesse às nossas metas de produto relacionadas à interatividade e ao encantamento dos usuários. Após analisar todo o leque de opções, tomamos a corajosa decisão (naquele momento) de escolher o Jetpack Compose, que ainda estava em pré-Alfa.
A partir daí, as equipes da Google Play Store e do Jetpack Compose no Google trabalharam em total coordenação para lançar e refinar uma versão do Jetpack Compose que atendesse às nossas necessidades específicas. Neste artigo, falaremos sobre nossa abordagem à migração e também sobre os desafios e benefícios encontrados ao longo do caminho, a fim de compartilhar alguns insights sobre como poderá ser a adoção do Compose para um app com muitos colaboradores.
Ao considerarmos o Jetpack Compose para nossa nova camada de renderização de IU, nossas duas maiores prioridades eram:
Já estamos escrevendo código de IU com o Jetpack Compose há mais de um ano e gostamos de como o Jetpack Compose simplifica o desenvolvimento de IUs.
Adoramos o fato de a escrita de IU exigir muito menos código, às vezes até 50% menos. Isso ocorre porque o Compose é um framework de IU declarativo que aproveita a precisão do Kotlin. O desenho e os layouts personalizados agora são chamadas de função simples, em vez de subclasses View com N substituições de métodos.
Vejamos, por exemplo, a tabela de avaliações:
As animações são um ótimo recurso do Compose por sua simplicidade e expressividade. Com o Compose, nossa equipe está criando recursos de movimento que encantam de forma inédita os usuários da Play Store. Com a natureza declarativa e as APIs de animação do Compose, nunca foi tão simples escrever animações sequenciais ou paralelas. Nossa equipe não teme mais todos os casos isolados de animações relativos a cancelamentos e encadeamentos de callback. Lottie, uma biblioteca de animação popular, já fornece APIs do Compose com as quais é muito simples trabalhar.
Você deve estar pensando: tudo isso parece ótimo, mas e quanto às dependências de bibliotecas que fornecem Views? É verdade: nem todos os proprietários de bibliotecas implementaram as APIs baseadas no Compose, principalmente no início da migração. Mas o Compose oferece interoperabilidade simples com Views por meio de suas APIs ComposeView e AndroidView. Fizemos uma integração bem-sucedida com bibliotecas populares, como ExoPlayer e YouTube’s Player, dessa maneira.
As equipes da Play Store e do Jetpack Compose trabalharam em total colaboração para garantir que a execução do Compose fosse tão rápida e livre de instabilidades quanto o framework de Views. Devido à forma como o Compose é empacotado no app (em vez de ser incluído como parte do framework do Android), essa era uma missão ambiciosa. A renderização de componentes individuais da IU na tela era rápida, mas o tempo total de carregamento de todo o framework do Compose na memória para apps era alto.
Uma das maiores melhorias de desempenho da adoção do Compose para a Play Store foi resultado do desenvolvimento de perfis de referência. Embora os perfis de nuvem ajudem a reduzir o tempo de inicialização do app e já estejam disponíveis há algum tempo, eles só se destinam à API 28 ou mais e não são tão eficazes para apps com atualizações de versões frequentes (semanais). Para combater isso, as equipes da Play Store e do Android trabalharam juntas em perfis de referência: um perfil empacotado e definido pelo desenvolvedor que pode ser especificado pelos proprietários de apps. Esses perfis são fornecidos com o app, são totalmente compatíveis com os perfis de nuvem e podem ser definidos no nível de especificidade do app e no nível de biblioteca (os adotantes do Compose terão isso gratuitamente). Com o lançamento dos perfis de referência, a Play Store teve uma redução do tempo de renderização inicial de sua página de resultados de pesquisa de 40%. Isso é incrível!
A reutilização de componentes de IU é uma mecânica básica do desempenho do Compose para renderização, particularmente em situações de rolagem. O Compose faz de tudo para ignorar as recomposições que ele sabe que podem ser ignoradas (por exemplo, porque são imutáveis). Mas os desenvolvedores também podem forçar o tratamento das composições como ignoráveis se todos os parâmetros atenderem aos requisitos de anotação de @Stable. O compilador do Compose também fornece um guia prático sobre o que está impedindo que funções específicas sejam ignoradas. Durante a criação de componentes de IU altamente reutilizados na Play Store e que eram usados com frequência em situações de rolagem, descobrimos que as recomposições desnecessárias estavam aumentando os tempos para a renderização de frames perdidos e, consequentemente, a instabilidade. Criamos um Modifier para identificar facilmente essas recomposições também em nossas configurações de depuração. Ao aplicar essas técnicas a nossos componentes de IU, conseguimos reduzir a instabilidade em 10% a 15%.
Outro componente-chave da otimização do Compose para o app da Play Store era ter uma estratégia detalhada de migração completa para todo o app. Durante os primeiros experimentos de migração, tivemos um problema com duas pilhas: a execução do Compose e da renderização de Views em uma única sessão do usuário consumia memória demais, principalmente nos dispositivos mais simples. Isso causava cortes durante as implementações do código na mesma página, mas também quando duas páginas diferentes (por exemplo, a página inicial e a página de resultados de pesquisa da Play Store) estavam em pilhas diferentes. Para atenuar essa latência de inicialização, era importante para nós ter um plano concreto para a ordem e a linha do tempo das páginas migradas para o Compose. Além disso, vimos que era útil adicionar o preaquecimento de curto prazo das classes comuns como temporárias até que o app estivesse totalmente migrado.
O desempacotamento do Compose do framework do Android reduziu a sobrecarga para a equipe que estava contribuindo diretamente com o Jetpack Compose, resultando em prazos de entrega mais curtos de melhorias que beneficiam todos os desenvolvedores. Conseguimos colaborar com a equipe do Jetpack Compose e lançar recursos como o armazenamento em cache de tipos de item LazyList, além de acelerar correções mais leves, como as alocações de objetos adicionais.
A adoção do Compose na Play Store foi uma bênção para os desenvolvedores de nossa equipe, e um grande avanço em qualidade e integridade de código. Todos os novos recursos da Play Store são criados com base nesse framework, e o Compose foi fundamental para desbloquear o aumento da velocidade e as transições mais suaves para os apps. Devido à natureza de nossa estratégia de migração para o Compose, não tivemos a chance de medir tão atentamente fatores como as mudanças no tamanho do APK ou na velocidade de compilação, mas tudo indica resultados bastante positivos! O Compose é o futuro do desenvolvimento de IUs do Android e, a julgar pela Play Store, não poderíamos estar mais satisfeitos!
Postar um comentário
Nenhum comentário :
Postar um comentário