Flutter: um novo framework de desenvolvimento mobile:
O Flutter é um framework de desenvolvimento híbrido para mobile, tanto Android quanto IOS, que trabalha em cima de widgets. Toda aplicação mobile precisa de uma maneira para lidar com chamadas assíncronas e para compartilhar estado entre as telas do aplicativo. E com o Flutter não é diferente, porém ele têm algumas funcionalidades, muito interessantes, para te auxiliar com isso: futures e providers.
Pensando em ajudar você a entender melhor como essas funcionalidades funcionam, escrevi um breve tutorial mostrando como implementá-las. Vamos lá?
Futures – a maneira como o flutter lida com funções assíncronas
Imagine que você é um garçom e a cozinha te avisa que um prato foi liberado. Logo, você irá demorar alguns segundos para buscar o prato e realizar a entrega para o cliente que fez esse pedido. Vamos chamar esta ação de buscarPratoNaCozinha. Veja como isso ficaria no formato de um future:
class Prato { String nome; int preco; Prato(int preco, String nome){ this.nome = nome; this.preco = preco; } } Future <Prato> buscarPratoNaCozinha(){ var prato = Future<Prato>.delayed( Duration(seconds: 4), () => new Prato(40, "Tropeiro completo"), ); return prato; }
Mas, e ai? Bom, com um future, você consegue renderizar a tela com um FUTURE BUILDER.
Vem que eu te explico como funciona: o Flutter possui essa funcionalidade chamada future builder. Com ela, você altera a tela para o seu usuário, baseado no estado atual da sua requisição assíncrona. Para simplificar, vamos considerar que nossa requisição possui apenas três estados:
- default:
,ela ainda não está completa, ou seja, não houve nenhum retorno; - hasData:
,que foi um sucesso e sua função assíncrona já retornou o valor; - hasError:
,ocorreu um erro na sua função assíncrona.
No caso da nossa chamada buscarPratoNaCozinha(), temos que:
- default: o garçom ainda não retornou com o prato para a mesa do cliente;
- hasData: já nos retornou um prato;
- hasError: o garçom deixou o prato cair no caminho para a mesa.
Veja como ficaria o código e o resultado:
FutureBuilder<Prato>( future: _future, builder: (BuildContext context, AsyncSnapshot<Prato> snapshot){ if (snapshot.hasData){ Prato prato = snapshot.data; //Widget para o prato. } else if (snapshot.hasError){ //Widget do erro, caso ele aconteça. } else{ //Widget para exibir o progresso. } } )
Note que um Future Builder recebe um future (a chamada assíncrona que ele irá realizar) e um builder (que ele irá renderizar na tela dependendo do estado da chamada). Toda vez que o estado muda, o Flutter chama o método builder novamente e identifica qual componente ele tem que renderizar, através das condições que colocamos dentro do builder.
Providers – como controlar o estado global da sua aplicação
Agora imagine que a cozinha desse restaurante é dividida em algumas partes, e que cada parte tem uma televisão onde eles veem quais são os pedidos. Por exemplo, uma parte da cozinha cuida do preparo das verduras, e outra cuida do preparo da carne. Como avisar para todos que um novo pedido chegou?
Existem abordagens diferentes, as mais comuns são: redux, BLoC e provider. Nesse tópico iremos implementar um provider, que foi a abordagem utilizada no nosso projeto em Flutter. Veja como ficou o código para o nosso primeiro provider:
class Pedidos with ChangeNotifier { final List<Prato> _pedidosPendentes = []; UnmodifiableListView<Prato> get pedidos =>
UnmodifiableListView(_pedidosPendentes); void realizarPedido(Prato prato) { _pedidosPendentes.add(prato); notifyListeners(); } }
Nele, temos uma lista privada de pratos, _pedidosPendentes, que será exibida para todas as partes da nossa cozinha, e dois métodos: realizarPedido, que adiciona um prato a nossa lista, e pedidos, que retorna uma instância imutável da lista _pedidosPendentes.
Agora, para continuar o fluxo de um provider, precisamos inserir um pedido, por meio do método realizarPedido, veja como fica:
void _inserirNovoPrato(BuildContext context, Prato prato){ Provider.of<PedidosModel>)(context, listen: false).realizarPedido(prato); } Widget _blocoPrato(BuildContext context, Prato prato){ BorderSide borda = BorderSide(width: 2.0, color: Colors.black); return InkWell( child: Padding( padding: EdgeInsets.only(top: 16), child: Container( padding: EdgeInsets.all(24), decoration: BoxDecoration( borderRadius: BorderRadius.circular(8), border: Border( top: borda, left: borda, right: borda, bottom: borda, ), color: Colors.white), child: Center(child: Text('${prato.nome}')), ), ), onTap: () => {_inserirNovoPrato(context, prato)}, ); }
Na parte destacada do código, temos um bloco para representar cada prato que pode ser preparado pela cozinha. Ao clicar no bloco, o método _realizarPedido é chamado, e nele temos o código para chamar o método do nosso provider:
Provider.of<PedidosModel>(context, listen:false).realizarPedido(prato);
Agora é quando a mágica acontece! Quando o realizarPedido do nosso provider é chamado, ele insere um registro na nossa lista _pedidosPendentes, e chama a função notifyListeners(). Ela vai avisar para todos aqueles que estão escutando o nosso provider que um novo pedido chegou, ou que a nossa lista mudou. Mas, como fazer para escutar as mudanças do nosso provider? É só criar um consumer!
Um consumer é apenas um listener para o nosso provider. Portanto, quando você cria um, você especifica a qual provider ele escutará, e depois implementa o método builder, que será renderizado na tela. Dentro do builder, você consegue acessar todos os métodos e atributos públicos do provider, inclusive o nosso método pedidos, que retorna a nossa lista de pedidosPendentes. Por fim, veja como fica o código de um consumer:
Container( padding: EdgeInsets.only(top: 100, left: 20, right: 20, bottom: 100), color: Colors.white, child: Consumer<PedidosModel>( itemCount: pratos.length, itemBuilder: (BuildContext context, int index){ return Container( padding: EdgeInsets.all(24), decoration: BoxDecoration( borderRadius: BorderRadius.circular(8), border: Border( top: borda, left: borda, right: borda, bottom: borda, ), color: Colors.white ), child: Center(child: Text('${pratos[index].nome}')), ), ), } ) )
Bom, termino esse post por aqui. Espero que esse breve tutorial tenha sido muito útil para você, que queria aprender um pouco mais sobre o Flutter!
Até a próxima!
Produtos Digitais
Confira outros artigos
FinOps: a ponte entre inovação tecnológica e sustentabilidade financeira nas organizações
Nos últimos anos, o FinOps tem se destacado como uma força vital na interseção entre o departamento financeiro e a TI, principalmente no que diz respeito à gestão de recursos em ambientes de nuvem. Essa solução nasceu da necessidade de alinhar os objetivos financeiros e operacionais das empresas, a fim de criar uma ponte sólida […]
Produtos Digitais
Desenvolvimento Android x iOS: 10 recomendações para o desenvolvimento produtivo
Entre agosto de 2022 e junho de 2023, o mercado de aplicativos móveis experimentou um crescimento notável, projetando um aumento anual de 13,4% até 2030, alcançando um mercado estimado em US$ 187,58 bilhões. E, certamente, a tendência é que essa expansão continue exponencialmente nos próximos anos. Portanto, agora é a hora de explorar as oportunidades […]
Produtos Digitais
Desenvolvimento Mobile ou Web: a integração de dispositivos para uma experiência omnichannel
Em 1977, Ken Olsen, fundador da DEC – Digital Equipment Corporation –, proferiu a frase “There is no reason anyone would want a computer in their home” (em tradução livre: “Não há motivo para alguém querer um computador em sua casa”). Já em 2007, a Apple confirmou que Olsen estava equivocado ao apresentar o primeiro […]
Produtos Digitais