Hoje em dia, é pouco provável que alguém que trabalhe com mobile ainda não tenha escutado a palavra “Flutter” e caso você estava em outro planeta e nunca tenha escutado, fique tranquilo, eu explicarei de uma maneira resumida o que ela é.
Flutter é uma estrutura de código aberto do Google para criar aplicativos multiplataforma podendo compartilhar recursos visuais como botões, cards, menus e muito outros ajudando a agilizar o desenvolvimento além de poder fazer customizações nos seus componentes conhecidos como Widgets e tudo isso é compilado nativamente a partir de uma única base de código, isto quer dizer que permite desenvolvimento mobile nas aplicações Android e iOS ao mesmo tempo.
Agora que minimamente você sabe que é Flutter, já consegue imaginar que acabou virando uma tendência de mercado o uso dela. Portanto, tive um desafio de analisar a possibilidade de uso no produto PagVendas um aplicativo de gestão para lojistas/vendedores da PagSeguro. E claro que falando assim, você deve ter pensado algumas coisas, como:
"Como não colocar?"
"Vai entregar mais rapido? Bora pro Flutter!"
"Por que ainda não colocou?"
Mas vamos com calma… paciência você deve ter meu jovem Padawan…
Alguns pontos precisam ser analisados como:
- Adesão do time, pois não temos pessoas com experiência em Flutter;
- Segurança;
- Experiência do usuário;
- Impacto no tamanho do APK/AAB ou IPA no caso do iOS;
- Possíveis impactos em perfomance;
- Impacto do uso nas maquininhas da PagSeguro que é uma peculiaridade do produto PagVendas;
- Arquiteturas e padrões com o Flutter / Boas práticas e bibliotecas comuns do mundo Flutter;
- Escalabilidade.
Para analisar todos estes pontos, fomentar novas perguntas e descobrir se realmente faria sentido a adoção do Flutter no projeto do PagVendas, decidimos implementar uma POC integrada ao projeto nativo.
Adesão do time
Primeiramente tudo é feito por pessoas, portanto estamos nos preocupando de como o time vai absorver esse tipo de informação e como vai ser a adesão do flutter na prática. E para auxiliar e estimar foi seguido uma linha de liberdade total para voluntários da POC para participar dessa iniciativa, além de criações de cerimônias como mentorias para ajudar na disseminação do conhecimento para todos os envolvidos a fim de nivelar o nível técnico do time.
Experiência do usuário
Com a POC do Flutter integrada ao projeto nativo, conseguimos reproduzir a mesma UI com a mesma UX e com a mesma experiência. Sem impactos neste item.
Segurança
Em relação em segurança não houve impactos relevantes já que as persistências de dados criptografados pôde ser realizada da mesma forma através de uso de channels, isto é, basicamente um canal que faz a comunicação do Flutter para o nativo ajudando chamar as informações de maneira segura mantendo a compatibilidade das plataformas nativas. Utilizando a solução nativa que temos hoje de para as requisições do aplicativo para todas as chamadas okhttp quem vem do Flutter.
E também foram feitos testes de engenharia reversa e não foi apontado nenhum ponto crítico.
Impacto no tamanho do APK/AAB ou IPA no caso do iOS;
A ideia desse tópico é avaliar o quanto vai aumentar a instalação para o usuário final, podendo trazer vários níveis de impactos. E foi visto que devido na plataforma Android existe uma mudança significativa sendo adicionado a parte do Flutter de acordo com cada tipo de processador como mostra a imagem abaixo:
Exemplo no Android antes tinha 47MB e subiu para 64MB
Houve um Crescimento 49,7% no iOS
Como em algumas situações onde o consumo de dados é pago pela própria empresa no cenário das Smarts/Terminal e é utilizado na Loja de aplicativos da PagSeguro logo não possui recursos das lojas AppleStore ou Google Play de usar pacote de apps para gerar e disponibilizar apk/ipa otimizados para cada configuração de dispositivo. Porém já foram planejadas algumas estratégias para compensar essa situação, como:
- Distribuição com controle apenas no wifi
- Separação de processadores;
- Fazer uma distribuição direto da fábrica.
Com isso tudo levantado isso não irá gerar nenhum impacto neste requisito.
Possíveis impactos em perfomance
Esse item não foi um problema devido ao o uso do Skia que é uma biblioteca de gráficos 2D com a função de desenhar os componentes nativos sem impactar a perfomance de maneira significativa, este artigo explica com muitos detalhes comparativos com vários cenários de estresse e um volume muito grande de animações e mesmo assim as diferenças entre FPS, GPU, CPU foram baixos, isto quer dizer que nos cenários que temos hoje no PagVendas que são telas de fluxos simples, portanto não teria nenhum problema.
Nos preocupamos com a inicialização do Flutter no nativo utilizando o FlutterEngine que é o contêiner através do qual o código Dart pode ser executado em um aplicativo nativo e conforme a documentação do Flutter acaba fazendo a ocupação de memória ao inicializar:
https://docs.flutter.dev/development/add-to-app/performance
E como a experiência do usuário poderia ser prejudicar ao sempre criar uma instância do FlutterEngine ( mesmo limpando na memória posteriormente ) ao colocar a inicialização junto com a inicialização dos nativos a experiência foi parecida com a do nativo não mostrando impactos.
Durante o uso da aplicação fiz o monitoramento usando o AndroidProfile num POCOX3 NFC no qual apresentou uma alocação maior ao abrir o aplicativo lembrando que pode ser variado de acordo com o dispositivo, mas durante o uso não houve impactos de perfomance e alterações após a inicialização independente das telas que abrem conforme imagem utilizando o mesmo cenário com apenas apks diferentes lembrando:
Com o uso do FlutterEngine constou 338MB
No uso normal constou 250MB
Mesmo não tendo acontecido nenhum tipo de impacto durante o uso no aplicativo num cenário de fluxo de tela com uma lista abrindo uma tela de detalhe é um item que precisamos dar mais de atenção, pois conforme o volume das telas em Flutter do projeto irão aumentando, ou com fluxos mais longos, podemos ter um aumento significativo. Sobre o impacto do uso nas Maquininhas da PagSeguro que é uma pecularidade do PagVendas. Hoje as maquininhas Smarts da PagSeguro utilizam Android 7 e 8 e mesmo não tendo a potência de um hardware comparado a smartphones mais atuais, não houve nenhum tipo de problema no durante o teste. Bora pro próximo.
Arquiteturas e padrões com o Flutter
Neste item fiz alguns experimentos e fui muito na linha do uso de tecnologias já conhecidas no mercado e vou listar as decisões que tomei em conjunto com a equipe sobre elas.
- Para o uso de injeção de dependência estamos utilizando o getIt;
- Para gerenciamento de estado após ter feito alguns experimentos com bloc, cubit e mobx o time entrou em consenso geral para o uso do mobx pela proximidade com o que já temos hoje nos projetos nativos. E todos esses itens foram tirando do próprio site do flutter de recomendações;
- Chamadas de redes estamos usando o Dio + Retrofit com tratamentos nos interceptors buscando as informações do nativo através dos channels;
- Para testes unitários está sendo usado o mockito e o fake_async para ajudar nos cenários de testes com o uso do Future;
- Para monitoramento está sendo usada o firebase crashlytics + a criação de channels para comunicação com o nativo sobre este item;
- Definimos o uso de clean no projeto com base no MVVM conforme a imagem;
- Na camada de “presentation” definimos o padrão com o nome de “Controller” .
Escalabilidade
Com todas as informações acima da para ver que o Flutter é escalável dentro do nosso projeto, além disso temos casos dentro da empresa que utilizam Flutter com um volume significativo de usuários(Pagbank) e também não foi encontrado algum tipo de limitação pensando neste tópico.
Após tudo isso irei relacionar os Prós e Contras do Flutter:
Prós:
- Criação de telas mais rápido;
- Interesse do time num todo para uso de uma nova tecnologia;
- Ganho de tempo devido a ser multi-plataforma;
- É escalável;
- Fácil de se integrar com o nativo;
- Componentes visualmente fieis ao nativo;
- Navegação fluída como se fosse nativo;
- Build rápido para desenvolver;
- Vasta documentação;
- Flutter se mantém bem atualizado aos recursos do nativo.
Contras:
- Ainda precisa refinar a parte de rotas do aplicativo nesse estudo devido ao uso do cache que vem no default fazendo com que as telas não sejam recarregadas novamente da maneira esperada;
- A linguagem Dart não está ainda tão atualizada como Kotlin ou Swift gerando frustrações quanto ao uso dela;
- Aumento grande no apk devido as bibliotecas do FlutterEngine para cada tipo de processador;
- Tive a sensação de que falta algumas partes serem ainda amadurecidas no desenvolvimento comparado ao nativo, como o ciclo de vida do Flutter inicialmente eu acredito que não atenda as necessidades que o mobile precise por exemplo;
- A utilização de algumas bibliotecas Flutter destoam da forma nativa, gerando estranheza, por exemplo o uso do Bloc ou getIt ou até do Retrofit junto com o Dio tem algumas pecularidades;
- Sempre tem que ter a atenção para o compilação manual, pois algumas classes precisam serem geradas manualmente nos seus respectivos módulos, fazendo com que você tenha o máximo de atenção neste processo;
- A documentação para tratar o tema da integração do Flutter com projetos nativos é existente porém rasa.
Mas e aí, dá para usar o Flutter num projeto 100% nativo?
Depois de todo esse estudo com certeza podemos dizer que é possível utilizar o Flutter num projeto nativo, as únicas considerações que faço é referente o nível de experiência do time, pois lembrando que estamos atuando em produtos já consolidados no mercado e resolver algum problema em produção de maneira eficaz requer conhecimento do assunto que você esteja trabalhando. Até por esse motivo a orientação inicial da minha parte para a empresa é que o Flutter seja utilizado em funcionalidades periféricas, isto é, funcionalidades não críticas. Tirando isso, acredito que o uso do Flutter é super factível para qualquer projeto e todos os pontos levantados e citados acima em nenhum deles foi visto como impeditivo, apenas como ponto de atenção a parte do uso de memória ao utilizar mais o FlutterEngine.
Tem um assunto ainda que me deixou desconfortável que pretendo deixar como próximos passos, que é esse reaproveitamento das telas que o Flutter faz de graça pra gente usado com o parâmetro maintainState, no qual acredito que pode ser um problema dependendo do volume de telas que naquela aplicação consiga ficar a aberta. No entanto, este é um efeito colateral do que o Flutter pode causar no projeto devido ao fator mais óbvio que é o desenvolvimento único para as duas plataformas.
Próximos passos:
Estudar e avaliar o uso da biblioteca nuvigator e goRoute para melhorar o tratamento de rotas no aplicativo; Montar melhor a estrutura de testes de widgets, pois o GetIt requer que seja montada toda a estrutura de DI mockada para poder inicializar os testes.
Agradecimentos:
Gostaria de agradecer todos os envolvidos dentro da empresa que participaram ou contribuíram na parte técnica: Raimundo Gonçalves, Felipe Martins, Felipe Menezes, João Otávio Huss, Carlos Eduardo Vieira, Thiago Passos e Jean Rodrigo. E ao pessoal da gestão que teve toda essa preocupação do envolvimento das pessoas e do projeto: Francine Moreira de Souza Cunha, Charles Lopes de Abreu
Tomara que isso tenha te ajudado de alguma forma e se achou o tema interessante acompanhe o blog da PagSeguro que terão mais casos de uso com exemplos reais de grande escala da empresa.