No dia a dia quando estamos desenvolvendo uma aplicação Flutter nos deparamos com situações que precisamos executar processos que levam um certo tempo e não queremos que trave o processo principal, como um dado de uma API por exemplo, uma tecnica que podemos utilizar é a de programação assíncrona que no Flutter é através das Futures.
Para utilizarmos as Futures existem 3 palavras reservadas: async, await e Future.
· await — esta palavra determina que a linha de execução irá esperar a execução de um outro método future (no caso a linha 2) antes de prosseguir a execução da função, aguardando que a future seja resolvida, isto é muito utilizado se o restante da função depende do retorno da Future que irá ser executada.
Lembrando que pode ser que a resolução da Future nem sempre é o estado esperado.
· async — serve para determinar que é assíncrono, geralmente é utilizado caso o método tenha uma chamada await.
· Future — determina que uma função irá retornar algo no “futuro”, ou seja, é uma função que levará um tempo até ser finalizada.

Basicamente quando se executa a Future pode estar em três estados.
· Ela pode estar uncompleted (incompleta), ou seja, ela ainda está em execução.
· Ela pode estar completa com valor
· Ela pose estar completa com erro
É possível e recomendável tratar esses estados em minha aplicação.
Vale destacar que Futures são apenas uma forma de simplificar as operações de Event Loops e cabe ressaltar que o código Dart é executado em apenas um thread (ou Isolate). Portanto, é importante lembrar que :
“EVENT LOOPS E FUTURES NÃO SÃO PROGRAMAÇAO PARALELA.”
Entao não se esqueçam: EVENT LOOPS E FUTURES NÃO SÃO PROGRAMAÇAO PARALELA.
Outra forma de lidar com as Futures é utilizando as funções then() e onError(). Elas permitem tratar os resultados e erros de forma mais organizada e simplificada.

Event Loops

No Dart ele possui um Fila de Eventos onde toda vez que uma Future é executada ele insere esse evento dentro do Event Queue para ser executado.

O Event Queue tem as seguintes características
· Ele é FIFO (First In First Out), ou seja, o primeiro evento que entra na fila é o primeiro a ser executado.
· Geralmente é utilizado quando há a necessidade de algum retorno.
· Possui baixa prioridade
Também temos um outro tipo de fila que são as filas de MicroTasks, que possuem as seguintes características
· Ele é FIFO (First In First Out), ou seja, o primeiro evento que entra na fila é o primeiro a ser executado.
· Geralmente é utilizado quando NÃO há a necessidade de algum retorno, funções simples.
· Possui alta prioridade
Então se eu tiver no meu Event loop a inserção de vários eventos e microtasks de forma desordenada ele será re-priorizado antes no início da execução da fila de forma que as microtasks sejam executados primeiro.

Nesse caso irá executar primeiro o MicroTaskA depois a MicroTaskB depois o EventA e finalmente o EventC.

O fluxo ficaria da seguinte forma

Então vamos analisar o código abaixo
import 'dart:async';
Future<void> main() async {
print('Main Primeiro');
scheduleMicrotask(() {
print('Microtask 1');
});
Future.delayed(const Duration(seconds: 2), () => print('Future Delayed'));
Future(() => print('Future 1'));
Future(() => print('Future 2'));
scheduleMicrotask(() {
print('Microtask 2');
});
Teremos o seguinte resultado, onde a main() será executada primeiro, após isso será executadas as microtasks e por fim os Future, deixando por último o que tem o dalay. Tudo seguinto o principio do First In First Out em cada fila.

Agora vamos olhar para outro exemplo mais complexo e analisar a saída.
import 'dart:async';
Future<void> main() async {
mA();
mB();
mC('Metodo main');
mD();
}
mA() {
print('Executando A');
}
mB() {
print('Iniciando B');
mC('Metodo B');
print('Finalizando B');
}
mC(String caller) {
print('Iniciando C chamado de $caller');
Future(
() => print('Iniciando Future C chamado de $caller'),
).then((value) => print('Finalizando Future C chamado de $caller'));
print('Finalizando C chamado de $caller');
}
mD() {
print('Executando D');
}

Note que quando temos o await nas chamadas das Futures o método é executado imediatamente e não é inserido no eventloop para processamento posterior
Sabia desse funcionamento das Futures? E lembrando que isso NÃO é paralelismo, para isto precisaremos trabalho com outro conceito que são as Isolates que trataremos em um próximo artigo.




