Oi! Boas-vindas ao nosso curso de Dart: aplicando assincronismo.
Eu me chamo Caio Couto Moreira, mas vocês podem me chamar de Kako.
Autodescrição: Cabelo cacheado loiro, nariz comprido, olhos castanho-esverdeados e uma barba curta. Estou usando uma camisa de botões de estampada com diversos desenhos em grafite.
Este curso é essencial para você que quer se aprofundar nos conceitos de Dart, especificamente em assincronismo: objetos, métodos e funções assíncronas, que são especiais para resolvermos problemas de espera de informações.
Quando queremos esperar um dado da Internet, de uma API ou do banco de dados, precisamos começar a trabalhar de forma assíncrona. É isso que aprenderemos nesse curso.
Eu irei apresentá-lo a novos objetos que lidam com o assincronismo, por exemplo, os objetos Future e Streams. Aprenderemos como eles funcionam, como manipulá-los e qual a necessidade deles em grandes projetos, quando nos comunicarmos com objetos externos, APIs ou banco de dados de grandes empresas.
Precisamos começar a entender essa questão de esperar por um dado e das formas assíncronas de se trabalhar, mas para isso é importante que tenham feito os outros cursos de Dart. Eles serão uma base teórica para este curso.
Neste curso trabalharemos com o projeto KakoBOT, que é um robô de inteligência artificial que produzimos e que vamos manipulá-lo para entender algumas questões de como funciona o assincronismo. Nosso KakoBOT já tem a sua inteligência, então ele fala conosco, perguntando como pode nos ajudar.
Nós poderemos interagir com ele através do terminal. Por exemplo, podemos perguntar "Que horas são?" e ele irá buscar para nós o horário que nós fizemos a pergunta. Também podemos agradecê-lo e ele responderá "De nada, fique à vontade c:". E se dizemos "Adeus" ele manda uma mensagem de despedida e encerra nosso KakoBOT.
Esse projeto está pronto para usarmos e, no decorrer das aulas, entenderemos sobre assincronismo e implementaremos isso ao nosso KakoBOT, adicionando tarefas de aguardar um tempo determinando ou alguma informação. Podemos também criar um limite de uso do nosso KakoBOT, mas entenderemos tudo isso com calma durante as aulas.
Por fim, gostaria de dizer que a melhor forma de aprender neste curso é através da aprendizagem ativa, fazendo uso dos vídeos e exercícios para aprimorar nosso conhecimento. Vocês também poderão usar o Fórum e o Discord para compartilhar sua aprendizagem, suas ideias e seu conteúdo, proporcionado visão crítica, confiança, eficiência e proatividade, que o mercado de trabalho deseja.
Vamos lá?
Agora que sabemos qual será o projeto do curso e o que iremos aprender, vamos começar pela base. Eu quero explicar para vocês o que é o Single Thread, como são organizar as tarefas no nosso projeto. Para isso essa aula será dividida em três partes:
Então vamos começar pelo fato do Dart ser uma linguagem síncrona, ou seja, single thread, então ele faz uma coisa por vez. Por exemplo, vamos analisar a ordem natural do nosso código.
void main() {
String kakoBot = 'KakoBOT:/n';
var a = true;
String usuario = '';
usuario = stdin.readLineSync(). toString();
print('-- Iniciando o KakoBOT, aguarde..--');
}
É um código bem simples com void main
, a String do KakoBOT, uma variável booleana true, outra String usuario
vazia, que em seguida recebe o valor que o usuário escreve no teclado, através do stdin
e, por fim, um print com uma mensagem que inicia o KakoBOT. Na maquinação do nosso Dart, cada linha desse código será processada por vez, então :
kakoBot
;a
usuario
com o valor vazio (notem que não é nulo;usuario
com a leitura de teclado (stdin
) do usuário;Então é um processo por vez. De uma forma mais visual, podemos observar o GIF abaixo de como as tarefas são processadas.
Observação: A animação demora um pouco para ser iniciada.
Então temos três tarefas: uma roxa, uma laranja e uma azul. Essas tarefas estão em um tipo de esteira e estão em uma ordem. A tarefa roxa está na frente, a laranja no meio e a azul no final.
O Dart fará um loop, representado pela engrenagem girando, que vai processar a tarefa roxa, depois a tarefa laranja e depois a azul, uma coisa de cada vez. Portanto imaginem esse conceito de esteira e engrenagem quando falamos sobre single threads.
Nós não conseguimos fazer duas tarefas ao mesmo tempo, precisamos esperar uma tarefa terminar seu percurso na engrenagem para começarmos outra tarefa, até terminar toas as tarefas necessárias no nosso projeto. É isso que quero dizer quando explico que o Dart é síncrono e uma linguagem single thread.
Esse tema é mais avançado, e acho legal vocês saberem. Além disso, para quem já está inserido no Flutter e na linguagem de Dart, terá uma experiência nova em relação à aspectos mais avançados.
Quando usamos Dart, como qualquer linguagem de programação, precisamos usar a memória do nosso computador, que é uma parte física que fica no processador do computador. Nós precisamos alocar parte dessa memória para o uso do Dart.
A seguir temos duas imagens com duas representações de memória que chamaremos de isolates:
Cada um desses blocos de memória, ou seja, cada retângulo verde, é responsável por finalizar uma tarefa. Portanto, se o Dart é assíncrono, ele usará só um bloco de memória.
Entretanto, na imagem temos dois modelos de isolates, e eu decidi colocar dois para vocês verem a diferença entre um isolate em uso (o da esquerda) e um completamente parado (o da direita). Na figura da direita conseguimos notar que tem alguns espaços em branco e na terceira linha e segunda coluna tem uma cédula com um tom bem claro de verde.
O que acontece é que, quando estamos concluindo uma tarefa, partes do nosso bloco de memória estão sendo usados, e não podemos usar dois blocos físico de memória ao mesmo tempo. Isso significa que é fisicamente impossível fazer duas tarefas simultâneas. Então na direita temos o isolate parado, ou seja, sem estar em uso.
Portanto isolates são espaços de memória dedicada para finalizar as tarefas do nosso projeto. Contudo, pensem no que acontece se essa tarefa demorar, às vezes nem por nossa culpa, mas porque ela precisa esperar por um valor.
Como é uma fila, existem vários problemas que podem acontecer se a tarefa demorar. O primeiro problema que pode acontecer é o atraso de tarefas. Então, voltando para o modelo da engrenagem, se a tarefa laranja trava a fila, ou seja, demora para ser concluída, a tarefa azul ficará esperando até que a conclusão da tarefa anterior ocorra.
Isso pode gerar, em muitos projetos, erro em tempo de execução, que é o famoso aplicativo travado. Para quem está trabalhando com Flutter já deve até ter visto alguns desses erros. E esse é um dos piores erros que podemos ter no mundo da programação, ou seja, não queremos que aconteça.
Essa demora na execução na tarefa também pode gerar dependências quebradas. Já aprendemos muito sobre isso, como criar classes, elas dependerem de outras classes. Isso aconteceu em um dos nossos primeiros exemplos, onde uma classe Fruta
era "pai" de uma classe Citrica
.
Então se a classe "Fruta" demorar para ser criada, a classe "Cítrica" também terá problemas. Portanto as dependências quebras e podem gerar problemas também.
Com isso notamos que tarefas que demoram muito atrapalham todo fluxo, então vou explicar sobre o assincronismo Dart, que foi a forma que encontramos para solucionar o problema de tarefas que demoram. Portanto, vamos voltar para o problema que é: temos duas tarefas para serem concluídas e, em uma delas, precisamos esperar por um valor.
Nós não precisamos processar essa tarefa, ou seja, fazer a parte trabalhosa, apenas precisamos esperar um valor que pode estar vindo de algum lugar, como da Internet. Nesse caso, qual seria a melhor alternativa para solucionar esse problema. Poderíamos:
Criar dois espaços de memória seria criar um segundo isolate, o que pode resolver nosso problema, mas deixa nosso projeto muito mais pesado, exigindo mais recursos, e não queremos isso. Porque o Dart é naturalmente single thread, e criando um novo espaço de memória, transformamos ele em multi-thread.
Essa solução pode ser legal, mas nem todos nosso problemas precisam ser solucionados criando novos espaços de memória. Sendo assim, essa não é a melhor alternativa.
No caso da criação de dois loops de memória é o equivalente a criar duas "engrenagens" para executar as tarefas. Entretanto, se um loop de memória está demorando para fazer uma tarefa e outro loop coloca mais uma tarefa em cima dela, teremos um problema.
Nós não temos espaço na memória para duas tarefas serem feitas ao mesmo tempo, portanto, essa não é uma alternativa plausível. Dessa forma a resposta correta é nenhuma das alternativas.
A resposta correta é utilizar o assincronismo, que é como um call-back, onde esperamos o momento certo para finalizar uma tarefa. Então se é uma tarefa na qual precisamos esperar por um valor, o ideal é deixar essa tarefa mais ao final na nossa fila de execução de tarefas.
Na próxima aula vamos conversar mais sobre assincronismo para entendermos a grande importância para tarefas que demoram a ser concluídas e porque essa é uma boa alternativa para o nosso problema.
Conversamos um pouco sobre single thread e assincronismo, sem nos aprofundarmos muito. Isso porque aprenderemos mais sobre assincronismo nessa aula.
Eu vou explicar para que o assincronismo serve, quando usamos e quando é melhor usá-lo. Para isso, nessa aula também teremos três tópicos:
O assincronismo realmente é necessário? Precisamos mesmo saber lidar com tarefas que demoram?
Em muitos projetos nós precisamos conversar com o exterior, por exemplo, um banco de dados, porque nossos projetos têm variáveis e informações. Grandes projetos como bancos e aplicativos famosos têm um servidor dedicado com informações que estão em outro lugar, ou seja, não estão no seu celular, e sim seguras em um servidor.
Podemos manipular esses dados da seguinte forma:
Então existem vários formatos e ações que podemos fazer com dados externos, mas o grande problema de usar informações de fora do nosso projeto é a demora que as coisas levam para acontecer. Por exemplo, já acessaram um site que demorou muito para recarregar, por mais que você tentasse recarregá-lo?
Isso não é culpa do site, e sim do servidor que hospeda as informações externas, então existe um delay e precisamos esperar por esses dados. Apesar da informação ser rápida, existe um tempo de espera mínimo.
Outro exemplo é o acesso à APIs. Para quem não sabe, e essa informação não é fundamental para este curso de assincronismo no Dart, APIs são Application Programming Interface (Interface de Programação de Aplicação). Elas possuem normas e protocolos para que possamos ter acesso à rede, e quando falamos em rede, nos referimos à Internet.
Por exemplo, queremos uma lista dos 100 melhores filmes de ação vinda da Internet ou uma foto do Google. Para termos acesso a essas informações temos também um tempo de espera, que precisa ser contabilizado.
Vamos imaginar que usamos o código de uma imagem da Internet que demora para ser carregada. Enquanto esperamos por ela, o projeto fica parado esperando que ela seja processada, e ele não conseguirá fazer nada, por mais que tentemos inicializá-lo.
A melhor forma de lidar com isso é usando o assincronismo, esperando essa imagem ser carregada. Isso porque essa informação não depende de nós, e sim da conexão com a Internet, que vai determinar o tempo de espera.
Enquanto isso, podemos fazer outras tarefas no nosso projeto. Essa é a grande ideia por trás do assincronismo: deixar tarefas que não dependem de nós carregando no final da fila de execução, enquanto fazemos outras atividades.
Outro exemplo que quero mostrar para vocês é o do Flutter, um framework que usa o Dart, como vocês podem observar nas imagens abaixo.
Importante: Relembrando que não é necessário saber Flutter para fazer o curso de Dart: aplicando assincronismo.
Esse exemplo é interessante porque existem botões nos aplicativos de Flutter. Esses botões ficam parados, esperando serem pressionados. No caso desse aplicativo, quando clicamos no botão de "+", no canto inferior direito, ele muda de tela.
Contudo, até pressionarmos esse botão ele não muda de tela. Esse é o exemplo de uma tarefa que fica esperando por uma ação, e enquanto esperamos essa ação, existem outras tarefas no app. Podemos querer usar outros botões do aplicativo ou arrastar a tela para olhar outras informações.
Sendo assim, é necessário que possamos fazer ações enquanto há tarefas em espera, ou o aplicativo permanecerá travado enquanto tiver um botão esperando uma ação. Desse forma, é imprescindível termos a habilidade de trabalhar com tarefas que precisam de tempo de espera e outras que podem ser executadas a qualquer momento.
Um primeiro e grande exemplo é o WhatsApp. Ele é um app de comunicação que troca mensagens em "tempo real". Eu digo "tempo real", entre aspas, porque demora um pouco.
Por exemplo, o WhatsApp pode parecer uma conversa entre duas pessoas, mas é uma conversa a três, a primeira pessoa, que é a emissora da mensagem, manda mensagem para um servidor, que avisa para segunda pessoa, que é a receptora, que a primeira está digitando. Por fim, o servidor manda para pessoa receptora a mensagem.
Então tem o caminho "Emissora > Servidor > Receptora" pela qual a mensagem passa antes de chegar. Se enquanto a mensagem não chega o WhatsApp travasse, seria complicado e frustrante, mas ele nos permite acessar outras conversas e mandar outras mensagens. Enquanto isso, ele espera a mensagem ser recebida ou enviada.
Então é importante entendermos o assincronismo nesse caso. Lembrando que quando falamos que é necessário esperar por algo, pensamos no conceito de delay, ou seja, um tempo de espera/atraso de um processo ou tarefa. É importante saberem esse conceito, porque usaremos muito ele no futuro para simular nosso assincronismo.
Outro exemplo famoso é o Instagram, que é uma rede social onde podemos compartilhar fotos e vídeos. Ele tem um sistema de curtida e de chat, ou seja, vários features, cada um com seu tempo de processo que precisa ser esperado.
Na prática, imaginem que estão com um belíssimo doce que vocês querem fotografar para postar nas redes sociais. Quando você fotografa e clica para compartilhar no Instagram, ele tem um tempo de espera para transformar a foto do seu celular em uma foto do Instagram e depois enviar essa foto para o servidor do Instagram.
Enquanto ele está enviando a foto para o servidor do Instagram e postando nas redes sociais, seria estranho se o Instagram travasse. Porém ele permite que enquanto você envia a postagem para o servidor, você pode usar sua rede social, vendo outras fotos, usando o chat, curtindo postagens. Tudo isso porque ele está fazendo duas coisas ao mesmo tempo: esperando o resultado enquanto te permite fazer outras tarefas.
Acho importante informar que isso não se aplica só ao Dart, tanto que, até onde eu sei, o WhatsApp e o Instagram não se aplicam apenas em Dart. Entretanto, ambos usam o assincronismo, porque vários projetos o usam.
Agora vou explicar rapidamente como usar o assincronismo no Dart, porque teremos várias aulas específicas de como aplicá-lo. Começarei, então, explicando sobre o objeto Future, que represente uma variável que só estará disponível futuramente.
Lembrete:
Future
é objeto que representa uma variável que só estará disponível no futuro.
Com o objeto Future
, podemos implementar o assincronismo e deixar uma espera na nossa linha de código. Por exemplo, no código abaixo temos um objeto Future
que espera três segundos e, após esse tempo, ele faz um print e retorna o valor 12.
Future<int> myFutureFunc() async {
await Future.delayed(Duration(second: 3));
print('I have a function in the Future!');
return 12;
I have a function in the Future!
12
Se conseguimos esperar para ações acontecerem, então conseguimos aplicar o assincronismo, basta entendermos como ele funciona.
Outro objeto que temos no Dart é o Stream, uma sequência e informações ou eventos que podem aparecer a qualquer momento, que sequer sabemos quando. Então é outro objeto que nos permite fazer tarefas enquanto informações estão aparecendo no nosso caminho.
Lembrete:
Stream
é um objeto que recebe uma sequência de dados/eventos assíncronos.
Stream<int> timedCounter(int interval, [int? maxCount]) async* {
int i = 1;
while(i != maxCount) {
await Future.delayed(Duration(second: interval));
yield i++;
}
Caso ainda não tenham entendido o Future e o Stream, não se preocupem. Por enquanto, entendam apenas porque precisamos do assincronismo, porque ele é importante para nós e que existem formas de aplicá-lo no Dart.
Mas antes de passarmos diretamente para os objetos Future
e Stream
no Dart, no próximo vídeo quero mostrar para vocês onde aplicaremos nosso conhecimento e como nosso projeto irá funcionar.
O curso Dart: entendendo assincronismo possui 149 minutos de vídeos, em um total de 38 atividades. Gostou? Conheça nossos outros cursos de Flutter em Mobile, ou leia nossos artigos de Mobile.
Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:
Impulsione a sua carreira com os melhores cursos e faça parte da maior comunidade tech.
1 ano de Alura
Assine o PLUS e garanta:
Formações com mais de 1500 cursos atualizados e novos lançamentos semanais, em Programação, Inteligência Artificial, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.
A cada curso ou formação concluído, um novo certificado para turbinar seu currículo e LinkedIn.
No Discord, você tem acesso a eventos exclusivos, grupos de estudos e mentorias com especialistas de diferentes áreas.
Faça parte da maior comunidade Dev do país e crie conexões com mais de 120 mil pessoas no Discord.
Acesso ilimitado ao catálogo de Imersões da Alura para praticar conhecimentos em diferentes áreas.
Explore um universo de possibilidades na palma da sua mão. Baixe as aulas para assistir offline, onde e quando quiser.
Acelere o seu aprendizado com a IA da Alura e prepare-se para o mercado internacional.
1 ano de Alura
Todos os benefícios do PLUS e mais vantagens exclusivas:
Luri é nossa inteligência artificial que tira dúvidas, dá exemplos práticos, corrige exercícios e ajuda a mergulhar ainda mais durante as aulas. Você pode conversar com a Luri até 100 mensagens por semana.
Aprenda um novo idioma e expanda seus horizontes profissionais. Cursos de Inglês, Espanhol e Inglês para Devs, 100% focado em tecnologia.
Transforme a sua jornada com benefícios exclusivos e evolua ainda mais na sua carreira.
1 ano de Alura
Todos os benefícios do PRO e mais vantagens exclusivas:
Mensagens ilimitadas para estudar com a Luri, a IA da Alura, disponível 24hs para tirar suas dúvidas, dar exemplos práticos, corrigir exercícios e impulsionar seus estudos.
Envie imagens para a Luri e ela te ajuda a solucionar problemas, identificar erros, esclarecer gráficos, analisar design e muito mais.
Escolha os ebooks da Casa do Código, a editora da Alura, que apoiarão a sua jornada de aprendizado para sempre.