Quando estamos desenvolvendo uma aplicação Flutter, é comum precisarmos acessar recursos externos, seja um arquivo, buscar dados de um banco de dados local ou até acessar algum recurso de uma API externa. Porém, todo recurso leva um tempo para retornar algo e precisamos liberar o app para que as outras tarefas continuem executando, “destravando” a execução e permitindo que a interface da tela, por exemplo, seja renderizada. Para isso, utilizamos o conceito de programação assíncrona no Flutter, conforme veremos durante este artigo.
Como funciona a programação assíncrona
Como vimos anteriormente, é comum que uma aplicação acesse recursos externos, o que pode levar um certo tempo até que o processo seja finalizado, porém, neste meio tempo, a aplicação precisa ser “liberada” para executar suas outras tarefas, como a renderização da interface da tela.
Para isso, precisamos trabalhar com um modelo de programação um pouco diferente do “habitual”, a programação assíncrona.
Basicamente, na programação assíncrona, uma tarefa pode ser executada enquanto espera o processamento de uma outra finalizar. Este modelo é diferente da programação que estamos mais habituados a trabalhar, chamada de programação síncrona.
Na programação síncrona, uma tarefa só é executada quando outra é finalizada, como podemos ver na imagem abaixo:
Já na programação assíncrona, diversas tarefas podem ser executadas em “paralelo”, dividindo o tempo com a execução de diferentes tarefas:
Este modelo é essencial para que uma tela acesse informações de um banco de dados, por exemplo, e enquanto espera estes dados, renderize a interface da página e este processo será detalhado no próximo tópico.
Curso Flutter - Fundamentos
Conhecer o cursoProgramação assíncrona no Flutter
Para utilizar o modelo assíncrono no Flutter, precisamos utilizar três palavras-chave: async, await e Future.
- O
async
determina que um método será assíncrono, ou seja, não irá retornar algo imediatamente, então o aplicativo pode continuar a execução de outras tarefas enquanto o processamento não é finalizado. - O
await
serve para determinar que o aplicativo deve esperar uma resposta de uma função antes de continuar a execução. Isso é muito importante pois há casos em que uma função depende do retorno de outra. - Já o
Future
determina que uma função irá retornar algo no “futuro”, ou seja, é uma função que levará um tempo até ser finalizada.
Implementando o modelo assíncrono
Imagine, então, um método que retornará todos os pets de um determinado banco de dados (não se preocupe com a forma que estes dados serão pesquisados). Como é algo que pode demorar um certo tempo até ser finalizado (temos que buscar os dados do banco de dados, processar as informações para, só então, retornar estes dados), precisamos criar uma função assíncrona, como podemos ver abaixo:
Future<List> getAllPets() async {
final dataList = await DbUtil.getData('pets');
_petList = dataList.map((pets) => Pet.fromMap(pets)).toList();
return _petList;
}
Curso Dart - Fundamentos
Conhecer o cursoNo código acima, estamos determinando que o método getAllPets()
irá retornar uma lista no “futuro”, por isso o uso do Future
. Além disso, essa função será assíncrona, sendo assim, precisamos indicar na assinatura do método a palavra async
.
Além disso, para retornar a lista de pets, precisamos buscar estes dados de um banco de dados. Porém, esta consulta não é imediata, levando um certo tempo para ser concluída.
Para que o Flutter “espere” até que alguma informação seja retornada do banco de dados, utilizamos o await
, indicando que o restante do método só poderá ser executado quando houver um retorno do método DbUtil.getData('pets')
.
Agora, sempre que o método getAllPets()
for invocado, o Flutter sabe que trata-se de um método assíncrono e, por isso, ele pode continuar a execução de outras tarefas enquanto este método “trabalha”.
Isso facilita (e muito) nosso trabalho, já que um app não pode ficar “travado” esperando o retorno de algo, o que comprometeria a usabilidade do usuário.
Conclusão
O conceito de assíncronismo é muito importante no Flutter/Dart (e em outras linguagens também), pois há casos em que um método levará um certo tempo para ser executado e o app não pode “travar” até que este retorno aconteça.