Introdução
Com este guia você aprenderá tudo o que é necessário sobre o Dart, para começar sua jornada com o Flutter.
Dart é a melhor linguagem de programação já feita pelo Google.
Sumário
- Por que o Flutter usa Dart?
- Conceitos importantes
main()
- Tipos de dados
- Variáveis
- Inferência
var / const / final
- Null Safety
- Operadores
if
switch
while
for
- Funções
- Classes
- Coleções
try / catch / finally
Future
async / await
- E agora?
- Referências
Por que o Flutter usa Dart ?
Dart possibilita que seu código seja executado em 2 tipos diferentes:
Interpretado (JIT = just-in-time): O código é interpretado e executado (neste caso, pela Dart virtual machine), mesmo que já esteja em execução. Assim como acontece no Python ou Javascript.
Compilado (AOT = ahead of time): O código é compilado e executado pela Dart VM. Assim como acontece no Java.
E qual a vantagem?
Para desenvolvedores: Uma experiência incrível, pois o código é interpretado e as alterações são refletidas em menos de 2 segundos.
Para os usuários: Um aplicativo altamente performático, já que o código foi compilado para a plataforma nativa na qual está sendo executado.
Resumindo, este é o motivo!
Mas caso queira se aprofundar, recomendo os materiais abaixo:
Primeiro artigo sobre este assunto
Documentação oficial do Flutter
Conceitos importantes
- É uma linguagem tipada, porém a declaração de tipos é opcional.
- Tudo em Dart é uma instância de
Object
. Qualquer coisa que possa ser armazenada em uma variável. Com exceção denull
. - Variáveis não podem ser declaradas com valores
null
. Para que elas aceitem, precisa-se declarar explicitamente esta possibilidade.
main()
Todo programa Dart (e aplicativos em Flutter, são programas Dart), iniciam na função main()
:
void main() {
print('Flutter Bootcamp');
}
Tipos de dados
Básicos:
- Numérico:
int
edouble
- Literal:
String
- Booleano:
true
efalse
- Coleções:
List
,Sets
eMaps
null
Existem ainda os tipos Symbols
e Runes
mas provavelmente não utilizará nenhum deles.
Especiais:
Object
: A super classe do Dart. Todos os objetos são herdados dela, com exceção do tipoNull
.Future
eStream
: Utilizadas para operações assíncronas.dynamic
: Desabilita a tipagem do Dart e permite que qualquer tipo de dados seja utilizado.void
: Utilizado como retorno (geralmente). Indica que este valor nunca é usado.
Variáveis
Variáveis armezenam referências. E em Dart, podemos declarar variáveis informando o seu tipo ou não (a tipagem é opcional):
String bootcamp = 'Flutter Bootcamp';
Neste caso, bootcamp
armazena a referência para um objeto do tipo String
com o valor de “Flutter Bootcamp”.
E esta sintaxe se aplica para todos os outros tipos de dados:
int lancamento = 2021;
double versao = 2.0;
List<String> aplicativos = ['Tempus', 'Menuo', 'Libria', 'Civitas'];
Map<String, Object> informacoes = {
'tags': ['flutter','dart'],
'descricao': 'Treinamento completo em Flutter',
'aplicativos': 6
};
Inferência
A declaração de tipos em Dart é opcional, ou seja, ambas declarações abaixo são válidas:
//tipo String declarado
String bootcampTipado = 'Flutter Bootcamp';
// tipo não declarado
var bootcampSemTipo = 'Flutter Bootcamp';
Por inferência, o Dart consegue identificar que bootcampSemTipo
é do tipo String
devido ao valor atribuido.
E o mesmo se aplica para todos os outros tipos de dados.
// int
var lancamento = 2021;
// double
var versao = 1.0;
// List<String>
var aplicativos = ['Tempus', 'Menuo', 'Libria', 'Civitas'];
// Map<String, Object>
var informacoes = {
'tags': ['flutter','dart'],
'descricao': 'Treinamento completo em Flutter',
'aplicativos': 6
};
var / const / final
Estes são os modificadores possíveis ao declarar variáveis:
var: Permite que o valor atribuído seja alterado.
final: O valor não pode ser alterado e não é conhecido em tempo de execução.
const: O valor não pode ser alterado e ja é conhecido em tempo de execução.
Sempre que possível, utilize
const
.
Null Safety
Desde a versão 2.12 (liberada em março de 2021), Dart suporta o modo null safety
por padrão.
Isso significa que devemos declarar explicitamente que uma variável pode ter valor null
. Caso contrário, o compilador indicará um erro:.
int idade;
print(idade);
❌ The non-nullable local variable 'idade' must be assigned before it can be used.
Este erro ocorre pois estamos acessando idade
antes de atribuir um valor à ela.
Ao utilizar o operador ?
, indicamos ao compilador que a variável pode ter valor null
.
int? idade;
print(idade);
✅ será imprimido o valor null
Operadores
Dart é uma linguagem moderna e possui todos os tipos de operadores tradicionais:
==
, !=
, &&
, ||
, >
, >=
, +=
, !
, e muitos outros.
Porém, precisamos destacar 3 que são amplamento utilizados:
-
?
- Indica que uma variável pode ter valornull
:// O valor null não pode ser atribuído à variavel ano int ano = null; // Em ambas declarações, o valor de ano é null. int? ano = null; int? ano;
-
??
- Retorna o valor da 1a expressão não sejanull
. Se fornull
, retorna a 2a expressão:dart // anoAtual possui valor de 2021, pois ano é null int? ano; var anoAtual = ano ?? 2021;
-
:
- Se a condição fortrue
, retorna o valor da 1a expressão. Caso não sejanull
, retorna a 2a expressão:dart // maiorIdade possui valor true, pois (idade é maior que 18) var idade = 34; var maiorIdade = idade > 18 ? true : false;
if
if (condicao) {
}
if (condicao) {
} else {
}
if (condicao) {
} else if (outraCondicao){
} else {
}
switch
switch (variavel) {
case: valor1;
break;
case: valor2;
break;
default; // opcional, acionado caso variavel não seja valor1 ou valor2
}
while
var ano = 2021;
while (ano < 2050) {
ano++;
}
var ano = 2021;
do {
ano++;
} while (ano < 2050);
for
for (var i = 0; i < 5; i++) {
}
for (item in minhaLista) {
}
Funções
São instruções de código que executadas em sequência.
Em Dart funções são objetos e do tipo Function
, ou seja, podem ser atribuídas às variáveis ou passadas como parâmetros.
bool isMaiorDeIdade(int idade) {
return idade >= 18;
}
Funções que executam apenas 1 instruçãos, podem ser declaradas usando a sintáxe =>
:
bool isMaiorIdade(int idade) => idade > 18;
Classes
Fornecem uma estrutura para a criação de objetos.
class FlutterBootcamp {
// atributos
int? aplicativos;
String? descricao;
List<String>? tags;
// construtor default(opcional)
FlutterBootcamp();
FlutterBootcamp(int aplicativos, String descricao, List<String> tags ){
this.aplicativos = aplicativos;
this.descricao = descricao;
this.tags = tags;
};
FlutterBootcamp(this.aplicativos, this.descricao, this.tags);
/*
Todas as declarações acima são válidas como construtor default da classe.
Porém, só é possível utilizar 1 delas.
Lembre-se: declarar o construtor default é opcional
*/
// funções
void exibirConteudo(){
}
}
No Flutter, outra funcionalidade muito utilizada da linguagem Dart são os named constructors
:
class Carro{
String? marca;
int? ano;
double? motor;
Carro.popular(){
motor = 1.0;
}
Carro.novo():
ano = 2021;
Carro.tesla(this.ano, this.motor):
marca = 'Tesla';
}
Agora, pode-se criar uma instância do objeto Carro
da seguinte forma:
// gol possui motor=1.0
var gol = Carro.popular();
// corollaCross possui ano=2021
var corollaCross = Carro.novo();
// modelS possui marca='Tesla', ano=2020, motor=2.0
var modelS = Carro.tesla(2020, 2.0);
Coleções
// List (os itens podem ser duplicados)
var aplicativos = ['libria', 'menuo', 'civitas'];
// Por inferência, aplicativos é um List<String>
// Set (os itens são únicos)
var aplicativos = {'libria', 'menuo', 'civitas'};
// Por inferência, aplicativos é um Set<String>
// Map
var aplicativos = {
1 : 'libria',
2 : 'menuo',
3 : 'civitas'
};
// Por inferência, aplicativos é um Map<int, String>
try / catch / finally
try {
} catch (e) {
} finally { // opcional
}
Future
São objetos utilizados para tratar operações assíncronas (sem sincronia).
Alguns exemplos:
- Consumir uma API via rede;
- Operações em banco de dados;
- Ler / gravar em um arquivo.
Qualquer operação que não seja concluída imediatamente é uma operação assíncrona.
Future é um objeto que representa uma operação assíncrona. Assim que a operação for concluída, o valor está pronto para ser usado.
void consultarTotalCommits() {
// quando buscarApi() concluir seu processamento, a função then() será executada e a variável total terá o valor foi retornado da API.
Future<int> totalCommits = buscarApi();
totalCommits.then((total) => tratarRetorno(total));
}
O compilador não irá esperar o retorno da API continuar o processamento.
async / await
As palavras-chave async
e await
, permitem escrever código com operações assíncronas similar à operações síncronas.
O código anterior, com async
e await
, poderia ser escrito da seguinte forma:
// deve-se usar async para indicar o uso do await dentro de uma função
void consultarTotalCommits() async {
// usando o await, fará o compilador esperar até que buscarApi() conclua seu processamento
int totalCommits = await buscarApi();
tratarRetorno(total);
}
O compilador irá esperar o retorno da API para continuar o processamento.
E agora ?
Parabéns! 👏
Tudo sobre linguagem Dart necessário para começar com Flutter já foi apresentado.
Porém, ainda existem muitos recursos para serem explorados.
Para continuar os estudos e se aprofundar, acesse o guia:
E também os cursos do Google Codelabs.
Com DartPad, é possível experimentar a linguagem diretamente no browser.