Buscar

ApostilaFlutter

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 80 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 80 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 80 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

TÉCNICO EM INFORMÁTICA
1. Introdução
Em geral desenvolver uma aplicação mobile é uma tarefa desafiante e complexa. Há muitos
frameworks disponíveis para desenvolver uma aplicação mobile. O Android fornece um framework nativo
baseado na linguagem Java e o iOS fornece um framework nativo baseado na linguagem Shift /
Objective-C.
Contudo para desenvolver uma aplicação que suporte os dois SOs, precisamos codificar em duas
linguagens diferentes usando dois frameworks diferentes. Para ajudar a superar esta complexidade que
existe nos framework mobile que suportam ambos SOs. Esses frameworks variam de simples framework
para aplicações mobile baseados em HTML (Os quais usam HTML como interface de usuário e
JavaScript para a lógica da aplicação) a frameworks específicos como linguagem complexa (que faz o
trabalho pesado de converter seus códigos para código nativo). Independente de sua simplicidade ou
complexidade, esses frameworks sempre tem muitas desvantagens, uma das principais desvantagens é o
baixo desempenho.
Neste cenário, Flutter - um framework de alto desempenho e simples baseado na linguagem Dart,
disponibiliza alta performance pela renderização da interface do usuário diretamente no canvas do
sistemas operacionais e não por meio de um framework nativo.
Flutter também oferece muitos widgets (UI) prontos para uso para criar uma aplicação moderna.
Esses widgets são otimizados para o ambiente mobile e design de aplicações usando widgets é tão
simples como o design HTML.
Para ser específico, uma aplicação Flutter é um widget. Widgets Flutter também suporta
animações e gestos. A lógica da aplicação é baseada na programação reativa. Widget podem
opcionalmente ter um estado.
Mudando o estado do widget, irá automaticamente (programação reativa) comparar o estado do
widget (novo e antigo) e renderizar o widget com somente as mudanças necessárias ao invés de
renderizar o widget inteiro novamente.
1.1. O que é programação reativa?
Programação reativa é um modelo de programação sobre fluxos de dados, potencialmente
assíncronos, em combinação com consumo/roteamento de eventos e propagação de estado.
1.2. Por que Programação Reativa?
Um dos desafios da Engenharia de Software atualmente são aplicações orientadas a alto volumes
de dados em tempo real. Usuários querem seus dados agora; querem ver seus tweets agora, confirmar
seus pedidos agora, jogos online precisam responder agora!
TÉCNICO EM INFORMÁTICA
As aplicações precisam igualmente responder a essas demandas agora. Não queremos que
nosso software fique bloqueado por um pedido de informações ou aguardando o resultado de uma
computação. Não queremos que nossa aplicação fique parada aguardando algum resultado, mas
precisamos exibi-los assim que estiverem prontos. Se lidamos com um bloco de informações, queremos
manipular resultados individuais, e não esperar que o conjunto inteiro seja processado. O comportamento
das aplicações evoluiu para lidar com dados empurrados. Então, precisamos de ferramentas de
implementação para construir um código capaz de reagir a eventos e informações.
1.3. Para que usar Programação Reativa?
Alguns casos de uso onde a programação reativa pode fazer sentido são:
 Eventos de UI (movimento do mouse, clicks de botão, etc): programadores desse tipo de aplicação
(digamos, em Javascript ou Android) estão acostumados a lidar com eventos de componentes, então
não há nada fundamentalmente diferente. As vantagens do paradigma reativo surgem com o conjunto
de operadores disponíveis para manipulação dos eventos, tornando simples tarefas como, por
exemplo, throttle de múltiplos clicks ou propagação de eventos para interfaces hiper-interativas;
 Chamadas para serviços externos (REST, RPC, etc): operações realizadas sobre HTTP são
bloqueantes por natureza; ao fornecer uma simplificação para o código assíncrono, a programação
reativa pode ajudá-lo a desbloquear o código de cliente HTTP, mas essa é a parte mais simples. Em
arquiteturas de serviços distribuídos (como microserviços), é comum um código de back-end construir
uma composição entre várias chamadas dependentes (o serviço “a” é invocado, e a resposta é
utilizada como parâmetro para invocar o serviço “b”, e sucessivamente). Frameworks reativos podem
ajudar a orquestrar chamadas dependentes de maneira natural, com a vantagem de NÃO bloquear o
código no cliente.
 Consumo de mensagens: processamento de mensagens com alta concorrência é um caso de uso
comum. Declaradamente, frameworks como o próprio RxJava, Reactor ou o Akka alegam serem
capazes de processar milhões de mensagens por segundo na JVM sem esforço. Sendo isso verdade
ou não, em maior ou menor grau, novamente sua implementação pode se beneficiar das ferramentas
disponíveis nesses frameworks para construir um pipeline de consumo de eventos/mensagens de
maneira muito simples.
 Abstração sobre processamento assíncrono: esse detalhe vai depender da ferramenta e da
linguagem que estiver utilizando, mas um dos pontos-chave dos frameworks reativos é fornecer uma
fundação simples para processamento assíncrono, desafogando sua aplicação dos detalhes mais
complexos envolvendo multithreading e permitindo que seu código possa se concentrar na lógica de
manipulação dos eventos.
TÉCNICO EM INFORMÁTICA
1.4. Recursos do Flutter
O framework Flutter oferece os seguintes recursos para os desenvolvedores:
 Um framework moderno e reativo
 Usa a linguagem de programação Dart que oferece um aprendizado fácil
 Desenvolvimento rápido
 Interfaces de Usuário bonitas e fluidas
 Grande variedade de widgets
 Roda a mesma aplicação em múltiplas plataformas
 Aplicações de alta performance
1.5. Vantagens do Flutter
 Flutter vem com widgets bonitos e customizáveis para alta performance de aplicativos mobile. Ele
atende a todas as necessidades e requisitos personalizados. Além disso, o Flutter oferece muito
mais vantagens, conforme mencionado abaixo:
 Dart tem um grande repositório de pacotes de classes os quais permitem ampliar os recursos dos
seus aplicativos
 Desenvolvedores precisam escrever apenas um código base para ser executado tanto no
Android como no iOS. O Flutter pode ser ampliado para outras plataformas também no futuro.
 O Flutter precisa de menos testes, pois sua base de código única possibilita escrevermos testes
automatizados válidos para abas as plataformas
 A simplicidade do Flutter o faz um bom candidato para o desenvolvimento rápido. Sua
capacidade de personalização e extensibilidade o tornam ainda mais poderoso.
 Com Flutter, desenvolvedores tem total controle sobre os widgets e seus layouts.
 Flutter oferece ótimas ferramentas para desenvolvimento, com a possibilidade de
recarregamento em tempo de desenvolvimento.
1.6. Desvantagens do Flutter
Apesar de suas muitas vantagens, o Flutter possui as seguintes desvantagens:
 Uma vez que codificado na linguagem Dart, os desenvolvedores precisam aprender uma nova
linguagem (Embora seja fácil aprende-la).
 Framework moderno tentam separar a lógica da interface do usuário, mas no Flutter a lógica e a
interface do usuário são integradas. Podemos superar isso usando uma codificação padronizada
usando módulos de alto nível para separar interface do usuário da lógica
 Flutter é outro framework para criar aplicações mobile. Os desenvolvedores estão tendo
dificuldades para escolher ferramentas certas em um segmento tão disputado.
TÉCNICO EM INFORMÁTICA
2. Criando uma aplicação no Flutter no VS Code
1. Abra o VSCode
2. Crie um novo projeto Flutter pressionando as teclas Ctrl + Shift + P e clique em Flutter: New
Project.
TÉCNICO EM INFORMÁTICA
3. Informe o nome do projeto e pressione Enter. O nome do projeto não pode conter letras
maiusculas, caracteres especiais e espaços em branco.
4. Selecione o local no qual será criada a pasta do projeto com os arquivos
TÉCNICO EM INFORMÁTICA
A estrutura básica de uma aplicação no Flutter é a seguinte:
.dart_tool - contém o arquivopackage_config.json que controla os pacotes utilizados na aplicação
.idea - contém arquivos de configuração do projeto específicos do VS Code
android - contém código fonte gerado automaticamente para criar uma aplicação Android
ios - contém código fonte gerado automaticamente para criar uma aplicação iOS
lib - pasta principal que contém o código Dart utilizado na estrutura do Flutter
lib/main.dart - arquivo principal de uma aplicação Flutter
test - a pasta contém um código Dart para testar uma aplicação Flutter
test/widget_test.dart - código exemplo (pode ser apagado)
.gitignore - controle de versão de arquivos do Git
.metadata - gerado automaticamente pelas ferramentas do Flutter
.packages - gerado automaticamente para controlar os pacotes Flutter
iml - arquivo de projeto utilizado pelo VS Code
pubspec.yaml - utilizado pelo Pub que é o gerenciador de pacotes do Flutter
pubspec.lock - gerado automaticamente pelo Pub que é o gerenciador de pacotes do Flutter
README.md - arquivo de descrição do projeto utilizando Markdown format
TÉCNICO EM INFORMÁTICA
5. Substitua o código dart no arquivo lib/main.dart com o código abaixo:
1. import 'package:flutter/material.dart';
2.
3. void main() => runApp(MyApp());
4.
5. class MyApp extends StatelessWidget {
6. @override
7. Widget build(BuildContext context) {
8. return MaterialApp(
9. title: 'Olá Mundo',
10. theme: ThemeData(
11. primarySwatch: Colors.blue,
12. ),
13. debugShowCheckedModeBanner: false,
14. home: Home(),
15. );
16. }
17. }
18.
19. class Home extends StatefulWidget {
20. @override
21. _HomeState createState() => _HomeState();
22. }
23.
24. class _HomeState extends State<Home> {
25. @override
26. Widget build(BuildContext context) {
27. return Scaffold(
28. appBar: AppBar(
29. title: Text("Primeiro App"),
30. centerTitle: true,
31. ),
32. body: Center(
33. child: Text("Olá Mundo"),
34. ),
35. );
36. }
37. }
TÉCNICO EM INFORMÁTICA
Vamos entender o código Dart linha a linha
Linha 1: importa o pacote Flutter material. O material é um pacote utilizado para criar a interface
com o usuário de acordo diretrizes de design especificadas pela Google para o Android.
Linha 3: é a inicialização de uma aplicação Flutter. O método main() chama a função runApp e
passa como parâmetro a classe MyApp. O objetivo da função runApp é anexar o widget fornecido pela
classe MyApp na tela da aplicação. O widget principal de uma aplicação será sempre um MaterialApp.
Linhas 5 - 17: O widget é usado para criar uma interface do usuário no framework Flutter.
StatelessWidget é um widget que não mantém o estados dos seus widgets filhos. MyApp herda de
StatelessWidget e sobrescreve o método build. O propósito do método build é criar uma parte da interface
do usuário da aplicação. Aqui o método usa o MaterialApp, um widget para criar a base da interface do
usuário da aplicação. Ele tem três propriedades title, theme and home.
title: é o título da aplicação
theme: é o tema utilizado pelo widget. Aqui, definimos como blue como a cor geral da aplicação
usando a classe ThemeData e sua propriedade primarySwatch.
home: é a junção de elementos da interface do usuário, que configuramos no outro widget, Home
Linhas 19 - 37: Home é um classe que herda StatefulWidget que é um widget que armazena as
mudanças de estados dos widgets filhos. A classe Home esta retornando um Scaffold que é um widget de
nível superior que junto ao MaterialApp é usado para criar uma interface de usuário conforme as diretrizes
do material design. O Scaffold tem duas propriedades importantes, appBar para mostrar o cabeçalho da
aplicação e o body que mostra o conteúdo atual da aplicação. AppBar é outro widget que renderiza o
cabeçalho da aplicação e que usamos na propriedade appBar. Na propriedade body usamos um widget
Center que centraliza o widget filho. O text é o widget filho do Center e apresenta o texto Olá Mundo no
centro da tela.
6. Clique no ícone e depois no botão e selecione o device que vai
rodar a sua aplicação conforme a figura abaixo
TÉCNICO EM INFORMÁTICA
7. A saída da sua aplicação será como a figura abaixo
3. Fundamentos do framework Flutter
3.1. Widgets
O conceito central do framework Flutter é que tudo é um widget. Widgets são basicamente
componentes de interface de usuário usados para criar a interface da aplicação. Widgets podem ser
comparados com blocos Lego; Juntando blocos você pode criar um objeto, e adicionando diferentes tipos
de bloco, pode-se alterar a aparência e o comportamento do objeto. Widgets são os blocos de construção
de um app Flutter, e cada widget é uma declaração imutável da interface do usuários. Em outras palavras,
widgets são configurações (instruções) para partes diferentes da UI.
No Flutter a aplicação é um widget de alto nível e seus elementos de interface são construidos
usando um ou mais filhos (widgets), os quais novamente usam seus widgets filhos, criando uma árvore de
widgets. Por exemplo, digamos que um arquiteto desenha uma planta de uma casa; todos os objetos
como paredes janelas e portas na casa são widgets e todos eles funcionam juntos para criar uma casa ou,
neste caso a aplicação. Esse recurso de composição nos ajuda a criar uma interface de usuário de
qualquer complexidade.
TÉCNICO EM INFORMÁTICA
Por exemplo, a hierarquia de widget da aplicação ola mundo (criada anteriormente) é a
especificada no seguinte diagrama:
 MyApp é criado pelo usuários e é construido usando widget nativo Flutter, MaterialApp
 MaterialApp tem uma propriedade home para especificar a interface do usuário da página
principal, que é novamente um widget criado pelo usuário, Home.
 Home é construida usando outro widget nativo do Flutter, Scaffold.
 Scaffold tem duas propriedades - body e appBar.
 body é usado para especificar a interface do usuário principal e appBar é usado para especificar
o cabeçalho da interface do usuário
 O cabeçalho da interface do usuário é construido usando o widget nativo Flutter AppBar e body é
construido usando o widget Center.
 O widget Center possui a propriedade child que referencia o conteúdo atual e é construido
usando um widget Text.
3.2. Gestos
Widgets Flutter suporta interação por meio de um widget especial o GestureDetector, que é um
componente não visível que captura as interações do usuário como por exemplo tapping, dragging, entre
outras dos seus widgets filhos. Muitos widgets nativos do Flutter suportam interação por meio do uso do
GestureDetector. Podemos também incorporar recursos de interatividade em um widget existente com a
combinação com o GestureDetector. Em capítulos posteriores o widget GestureDetector será explorado
de maneira mais aprofundada.
TÉCNICO EM INFORMÁTICA
3.3. Conceito de estados
Os widgets Flutter suportam a manutenção de estados fornecendo um widget especial, o
StatefulWidget. O widget precisa ser filho do StatefulWidget para suportar a manutenção de estado e os
que não necessitam de suporte para manutenção de estado devem ser filhos do StatelessWidget.
3.4. O ciclo de vida do StatefulWidget
Um StatefulWidget é construido baseado na sua própria configuração, mas pode mudar
dinamicamente. Por exemplo a tela mostra um ícone com uma descrição, mas valores podem mudar
baseados na interação do usuário, como escolher um ícone ou descrição diferente. Este tipo de widget
tem um estado mutável que pode ser mudar com o tempo. O widget stateful é declarado com duas
classes, classe StatefulWidget e a classe State. A classe StatefulWidget é reconstruida quando a
configuração do widget muda, mas a classe State pode persistir (permanecer), melhorando o
desempenho. Por exemplo quando o estado muda, o widget é reconstruido. Se o StatefulWidget é
removido da árvore e então inserido novamente na árvore em algum momento no futuro, um novo estado
do objeto é criado.
Observe que sob certas circunstâncias e restrições, você pode usar uma GlobalKey (chave
exclusiva em todo o app) para reutilizar (não recriar) o estado do objeto; contudoglobal keys são custosas
e a menos que sejam necessárias, considere não utilizá-las.
Você pode chamar o método setState() para notificar o framework que este objeto mudou e o
método build do widget é chamado (agendado). Você deve configurar os novos valores do estado no
método setState().
O exemplo seguinte mostra uma estrutura base do StatefulWidget e a Figura ? apresenta o ciclo
de vida do widget. Você tem duas classes a ExemploEdit que herda de StatefulWidget e a
_ExemploEditState.
class ExemploEdit extends StatefulWidget {
@override
_ExemploEditState createState() => _ExemploEditState();
}
class _ExemploEditState extends State<ExemploEdit> {
@override
Widget build(BuildContext context) {
return Container();
}
}
TÉCNICO EM INFORMÁTICA
Figura ?. Ciclo de vida do StatefulWidget
Você pode sobrescrever partes diferentes do StatefulWidget para customizar e manipular dados
em pontos diferentes do ciclo de vida do widget. A tabela 1 mostra algumas das principais overrides do
widget e a maioria das vezes você usará os métodos initState(), didChangeDependencies(), and dispose().
Você usará o método build() todas as vezes para construir sua interface do usuário.
TÉCNICO EM INFORMÁTICA
Tabela 1: Ciclo de vida do StatefulWidget
Método Descrição Código exemplo
initState()
Chamado uma vez
quando esse objeto é
inserido na árvore
@override
void initState() {
super.initState();
print('initState');
}
dispose() Chamado quando esse
objeto é removido da
árvore
permanentemente
@override
void dispose() {
print('dispose');
super.dispose();
}
didChangeDependencies()
Chamado quando o
estado this do objeto é
mudado
@override
void didChangeDependencies() {
super.didChangeDependencies();
print('didChangeDependencies');
}
didUpdateWidget- (Contacts
oldWidget)
Chamado quando a
configuração do widget
muda
@override
void didUpdateWidget(Contacts
oldWidget) {
super.didUpdateWidget(oldWidget);
print('didUpdateWidget:
$oldWidget');
}
deactivate()
Chamado quando o
objeto é removido da
árvore
@override
void deactivate() {
print('deactivate');
super.deactivate();
}
build(BuildContext context) Pode ser chamado
várias vezes para criar
a interface do usuário,
e o BuildContext
controla a localização
desse widget na árvore
de widgets.
@override
Widget build(BuildContext context) {
print('build');
return Container();
}
setState() Notifica o framework
que o estado deste
objeto mudou para
agendar a chamada de
construção para este
estado do objeto
setState(() {
name = _newValue;
});
TÉCNICO EM INFORMÁTICA
3.5. O ciclo de vida do StatelessWidget
Um StatelessWidget é construido baseado em suas próprias configurações e não muda
dinamicamente. Por exemplo, a tela mostra uma imagem com uma descrição e não mudará. O stateless
widget é declarado como uma classe. O método build (as partes da interface do usuário) do widget
stateless podem ser chamadas de três diferentes cenários. Pode ser chamado na primeira vez que o
widget é criado, quando o pai do widget é alterado e quando e quando um widget herdado
(InheritedWidget) é alterado.
O seguinte código exemplo mostra a estrutura base do StatelessWidget e a Figura ? apresenta o
ciclo de vida do widget.
class ExemploList extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container();
}
}
Figura ?. Ciclo de vida do widget Stateless
3.6. Layers
O conceito mais importante do framework Flutter é que o mesmo é agrupado em múltiplas
categorias em termos de complexidade e claramente organizado em layers de complexidade decrescente.
Um layer é construido sua próxima camada imediata. A camada superior é um widget específico para
Android e iOS. O próximo layer tem todos os widgets nativos do Flutter. O próximo nível é o layer de
renderização que é o componente renderizador de baixo nível e renderiza todo o aplicativo flutter. Os
layers descem para o código específico da plataforma principal.
TÉCNICO EM INFORMÁTICA
A visão geral de um layer no Flutter é especificado no diagrama abaixo:
TÉCNICO EM INFORMÁTICA
4. Introdução a linguagem Dart
Dart é uma linguagem de programação open-source de propósito geral. Originalmente
desenvolvida pela Google. É uma linguagem orientada a objeto com uma sintaxe C-style sendo utilizada
pela Google em alguns de seus maiores produtos como o Google AdWords. Disponibilizada ao público
em 2011, Dart é usado para construir aplicações mobile, web e server. Dart é produtivo, rápido, portable e
acima de tudo reativa. Se você esta familiarizado com as linguagens C#, C++, Swift, Kotlin, Java e
JavaScrip será capaz de começara a desenvolver em Dart rapidamente. Mas não se preocupe, mesmo
que você não esteja familiarizado com essas outras linguagens, Dart é uma linguagem simples de
aprender, e você pode começar relativamente rápido.
Quais são os benefícios de usar o Dart?
Em Dart código é transformado de uma só vez antes de atingir as plataformas que o executam, o
processo é chamado de Compilação AOT (Ahead-Of-Time). Em outras palavras não intermediários para
interpretar de uma linguagem para outra, não havendo pontes. A compilação AOT é usada quando
compila seu App para o modo release (como a Apple App Store e o Google Play).
Dart também é compilado just-in-time (JIT) tornando mais rápido a exibição das mudanças do seu
código utilizando o recurso Flutter stateful hot reload. A compilação (JIT) é usado quando depura seu app
rodando em um simulador/emulador.
Uma vez que Flutter usar Dart, não existe a necessidade usar linguagens diferentes para criar
interface de usuário e a lógica da aplicação.
Flutter renderiza de 60 frames por segundo (fps) a 120fps para dispositivos com essa capacidade.
Quanto mais fps mais suave o aplicativo.
4.1. Comentando códigos
Comentários ajudam a legibilidade do código, desde que não exagere. Comentários podem ser
usados para descrever a lógica e as dependências do app. Há três tipos de comentários: linha única,
múltiplas linhas e comentários de documentação. Comentários de linha única são normalmente utilizados
para adicionar descrições curtas. Comentários de linhas múltiplas são mais adequados para descrições
que possuem várias linhas. Comentários de documentação são usados para documentar completamente
uma parte do código, geralmente fornecendo explicações detalhadas e exemplos de códigos nos
comentários.
O comentário com uma única linha inicia com //, e o compilador Dart ignora tudo até o fim da linha.
//Este é um comentário de uma única linha
Comentários de múltiplas linhas iniciam com /* e terminam com */ e o compilador Dart ignora tudo
entre as barras.
TÉCNICO EM INFORMÁTICA
/*Este é um exemplo de bloco de
comentários com múltiplas linhas*/
Os comentários de documentação inicia com ///, e o compilador Dart ignora tudo até o final da
linha, a menos que esteja entre colchetes. Usando colchetes você pode consultar classes, métodos,
campos, variáveis de nível superior, funções e parâmetros. No exemplo seguinte a documentação gerada,
[FilterBy], se torna um link para a documentação da API da classe. Você pode usar a ferramenta de
geração de documentação do SDK (dartdoc) para analisar o código Dart e gerar documentação HTML.
/// Multiple filter options
///
/// Different [FilterBy]
enum FilterBy {
COMPANY,
CITY,
STATE
}
4.2. Função Main()
Todo app deve ter uma função de alto nível main(), que é a inicialização do app. A função main() é
onde a execução do app inicia e retorna um void com parâmetro opcional utilizando um objeto
List<String>. Cada função pode retornar um valor e para a função main() o valor retornado é do tipo void
(vazio, não contém nada) isso significa que não há retorno de valor.
No código seguinte, são apresentadas três formas diferentes de usar a função main(). Todas as
três formas de chamar a função main() são aceitas, mas por questões de legibilidade do código, por
padrão se utiliza a sintaxe de seta void main() => runApp(MyApp());
// sintaxe seta
void main() => runApp(MyApp());
// ou
voidmain() {
runApp(MyApp());
}
// ou com uma lista de argumentos string
void main(List<Strings> filters) {
print('filters: $filters');
}
TÉCNICO EM INFORMÁTICA
4.3. Declarando variáveis
Na seção anterior você aprendeu que a função main() é a inicialização do app e antes de começar
a escrever códigos, é importante aprender sobre variáveis em Dart. Variáveis armazenam referencias a
um valor. Alguns tipos de variáveis internas são números, strings, lists, maps entre outros.
Você pode usar a palavra reservada var para declarar uma variável sem especificar o tipo. O Dart
infere o tipo da variável automaticamente. Contudo não há nada de errado com usar var como uma
preferência pessoal. Declarar o tipo de variável facilita a legibilidade do código e é mais fácil saber que
tipo de valor é esperado. Ao invés de usar var, use os tipos de variáveis esperados: double, String e assim
por diante. Uma variável não inicializada tem um valor null. Quando declara-se uma variável se atribuir um
valor inicial, a mesma é chamada de não inicializada. Por exemplo, uma variável do tipo string é declarada
como String TituloLivro; e não é inicializada porque TituloLivro tem um valor igual a null (não valor).
Contudo se declara-la com um valor inicial String TituloLivro = “Aprendendo Flutter” o valor de TituloLivro
é igual a Aprendendo Flutter.
Use final ou const quando quiser que o valor inicial da variável são seja modificado. Use const
para variáveis que precisam ser tornadas constantes em tempo de compilação, significando que o valor é
conhecido em tempo de compilação.
Agora que sabe que variáveis armazenam referencias a valores, a seguir aprenderemos
opções para declarar variáveis. Em Dart todas variáveis são declaradas públicas (disponível para toda a
aplicação) por padrão, mas começar o nome da variável com um underscore (_) torna a variável privada.
Declarando uma variável privada, você esta dizendo que a mesma só pode ser acessada na função ou
classe na qual foi declarada. Observe que alguns tipos de dados em Dart começam com letra minúscula
como double e alguns com letra maiúscula como String.
E se o valor de uma variável não precisar mudar? Comece a declaração da variável com as
palavras final ou const. Use final quando o valor é atribuído em runtime (pode ser mudado pelo usuário).
Use const quando o valor é conhecido em tempo de compilação (no código) e não será mudado em
runtime.
// Declaração sem especificar o tipo - Inferência de tipo
var filtro = “empresa”;
// Declarando tipo
String filtro = “empresa”;
// Variável não inicializada tem um valor null
String filtro;
// Valor não será mudado
final filtro = “empresa”;
// ou
final String filtro = “empresa”;
TÉCNICO EM INFORMÁTICA
// ou
const String filtro = “empresa”;
// ou
const String filtro = “empresa” + filterOption;
// Variável Pública (o nome da variável sem underscore)
String userName = “maria”;
// Variável privada (o nome da variável começa com underscore)
String _userID = 'XW904';
4.3.1. Números
Declarar variáveis como número restringe os valores aceitos a números somente. O Dart fornece
dois tipos numéricos: int (inteiros) e double (reais). Ambos int e double permitem números positivos e
negativos e você pode inserir números extremamente grandes e precisão decimal, pois ambos usam
valores de 64 bits (memória do computador).
// Integer
int contador = 0;
double preco = 0.0;
preco = 125.00;
4.3.2. String
Declarar variáveis como String permite valores do tipo cadeia de caracteres. Para adicionar uma
única linha de caracteres, pode-se utilizar uma aspas simples ou duplas como ‘carro’ ou “carro”. Para
adicionar múltiplas linhas de caracteres use três aspas simples, como ‘’’carro’’’ Strings podem ser
concatenadas (combinadas) usando um operador (+) ou usando aspas simples ou duplas adjacentes.
// Strings
String defaultMenu = 'main';
// Concatenação de String
String combinedName = 'main' + ' ' + 'function';
String combinedNameNoPlusSign = 'main' ' ' 'function';
// String multi-line
String multilineAddress = '''
123 Any Street
City, State, Zip
''';
TÉCNICO EM INFORMÁTICA
4.3.3. Booleano
Declarar variáveis como bool (booleana) permite um valor lógico true (verdadeiro) ou false (falso)
// Booleans
bool isDone = false;
isDone = true;
4.3.4. List
Declarando variáveis como List (pode ser comparada como um array) permite que múltiplos
valores sejam informados para a mesma variável. E se caracteriza como um grupo ordenado de objetos.
Em programação um array é uma coleção iterável (acessada sequencialmente) de objetos, com cada
elemento sendo acessado por um índice de posição ou uma chave (key) Para acessar elementos o List
usa como posição inicial o índice 0 e o ultimo elemento é o tamanho do List menos 1 (uma vez que o
primeiro elemento do List esta na posição 0 e não 1).
Um List poder tem o tamanho fixado ou dinâmico, dependendo da necessidade. Por padrão, um
List é criado como dinâmica usando List() ou [ ]. Para criar um List de tamanho fixo adiciona-se o número
de posições que se deseja, usando este formato: List(25). O exemplo a seguir utiliza a interpolação de
String na instrução print: print('filtro: $filtro')
// List dinânica
List contatos = List();
// or
List contatos = [];
List contatos = ['Linda', 'John', 'Mary'];
// List de tamanho fixo
List contato = List(25);
// Lists - Em Dart um List é um array
List listOfFilters = ['company', 'city', 'state'];
listOfFilters.forEach((filter) {
print('filter: $filter');
});
// Resultado da instrução print
// filter: company
// filter: city
// filter: state
TÉCNICO EM INFORMÁTICA
4.3.5. Maps
Maps são listas compostas de chave e valor que permitem recuperar valores pelo o ID da chave. A
chave e o valor podem ser qualquer tipo de objeto, como String, números, entre outros. Tenha em mente
que a chave precisa ser única uma vez que o valor é recuperado pelo ID da chave.
// Maps - Um objeto que associa chaves e valores.
// Key: IDvalor - 'KeyValue': 'Valor'
Map mapFiltros = {'id1': 'compania', 'id2': 'cidade', 'id3': 'estado'};
// Mudar o valor da item com a chave id3
mapFiltros['id3'] = 'meu filtro';
print('Obtenha o fitro com id3: ${mapFiltros['id3']}');
// Resultado da instrução print
// Obtenha o fitro com id3: meu filtro
4.3.6. Runes
Em Dart declarar uma variável como Runes da suporte a códigos Unicode UTF-32. Unicode define
um valor numérico para cada letra, caractere especial e símbolos. O Dart usa a sequencia de unidades de
código UTF-16 para representar um valor Unicode UTF-32 a partir de uma sintaxe especial requerida de
String (\uXXXX). \uXXXX é um exemplo de código Unicode no qual XXXX é um valor hexadecimal de
quatro dígitos. Runes retorna um valor inteiro do código Unicode; então você usa
String.fromCharCodes() para alocar uma nova String para charCode especificado.
// Para o emoji anjo sorridente Unicode é u+1f607
// Remova o sinal de mais e abra uma chave antes do número e a feche após
Runes meuEmoji = Runes('\u{1f607}');
print(meuEmoji);
// Resultado da instrução print
// (128519)
print(String.fromCharCodes(meuEmoji));
// resultado
// x
TÉCNICO EM INFORMÁTICA
4.4. Usando operadores
Um operador é um símbolo usado para executar operações aritméticas, lógicas, relacionais, teste
de tipo, atribuição e condicional lógica.
As tabelas de 2 a 8 apresentam os operadores comuns de cada categoria. Como exemplo foram
usados valores literais ao invés de variável para simplificar a escrita.
Tabela 2: Operadores aritméticos
Operador Descrição Código exemplo
+ Adição 7 + 3 = 10
- Subtração 7 - 3 = 4
* Multiplicação 7 * 3 = 21
/ Divisão 7 / 3 = 2.33
Tabela 3: Operadores relacionais
Operador Descrição Código exemplo
== Igual 7 == 3 = false
!= Diferente 7 != 3 = true
> Maior que 7 > 3 = true
< Menor que 7 < 3 = false
>= Maior ou igual
7 >= 3 = true
4 >= 4 true
<= Menor ou igual
7<= 3 = false
4 <= 4 = true
Tabela 4: Operadores de testes de tipo
Operador Descrição Código exemplo
as
Usado para criar um alias na importaçãode
bibliotecas Import 'travelpoints.dart' as travel;
is
Se o objeto contém o tipo específico é
retornado true if (points is Places) = true
is!
Se o objeto contém o tipo específico é
retornado false (Não é normalmente usado) 7 * 3 = 21
Tabela 5: Operador ternário
Operador Descrição Código exemplo
condição ? valorTrue : valorFalse
Se a condição avaliada retornar true, o
retorno é o valorTrue. Se a condição
avaliada retornar false o valorFalse é
retornado
(7 > 3) ? true :
false = true
(7 < 3) ? true :
false = false
TÉCNICO EM INFORMÁTICA
Tabela 6: Operadores de atribuição
Operador Descrição Código exemplo
= Atribuição de valores 7 = 3 = 3
??=
Atribui o valor somente se a variável que está sendo
avaliada tem um valor null
Null ??= 3 = 3
7 ??= 3 = 7
+= Adiciona o valor indicado a variável 7 += 3 = 10
-= Subtrai o valor indicado da variável 7 -= 3 = 4
*= Multiplica o valor indicado pela variável 7 *= 3 = 21
/= Divide a variável pelo valor indicado 7 /= 3 = 2.33
Tabela 7: Operadores lógicos
Operador Descrição Código exemplo
!
É o operador lógico ‘not’. Retorna o valor oposto da
variável/expressão if (!(7 > 3)) = false
&&
&& é o operador lógico ‘and’. Retorna true se todos os
valores das expressões/variáveis forem verdadeiros
if ( (7 > 3) &&
(3 < 7) ) = true
if ( (7 > 3) &&
(3 > 7) ) = false
!!
!! é o operador lógico ‘or’. Retorna true se pelo menos um
dos valores das expressões/variáveis forem verdadeiros
if ( (7 > 3) ||
(3 > 7) ) = true
if ( (7 < 3) ||
(3 > 7) ) = false
Tabela 8: Notação em cascata
Operador Descrição Código exemplo
!
A notação em cascata é representado por dois pontos(..) e
permite efetuar uma sequencia de operações no mesmo
objeto
if (!(7 > 3)) = false
TÉCNICO EM INFORMÁTICA
4.5. Usando instruções de controle de fluxo
Para controlar o fluxo lógico no código Dart observe as seguintes instruções de fluxo:
 if e else são as instruções de fluxo mais comuns; Elas decidem que trecho de código será
executado com base na análise de expressões condicionais.
 O operador ternário é similar as instruções if e else, mas é usado somente quando há somente a
análise de uma condição.
 O loop for permite a iteração em uma lista de valores.
 while e do-while são uma dupla comum. Use o loop while para avaliar a condição antes de
inicializar o loop e use do-while para avaliar a condição depois da execução de uma iteração do
loop.
 while e break são úteis se você precisa parar a avaliação da condição no loop.
 continue é para quando você precisa parar a iteração corrente e inicializar o próximo ciclo de
iteração.
 switch e case são alternativas para as instruções if e else, mas requer uma clausula default.
4.5.1. if e else
A instrução if analisa uma expressão lógica e se o retorno desta expressão for true (verdadeiro) o
bloco de instruções associadas ao if é executado. A expressão lógica é envolvida por parênteses
(expressão lógica) e o bloco de instruções envolvido por chaves {conjunto de instruções}. O if também
suporta a instrução else que é contém o bloco de instruções que serão executados se a condição lógica
analisada retornar false (falso). Também é possível utilizar múltiplas instruções else if em um em um bloco
if, mas somente um else para fechar o bloco condicional. No exemplo seguinte verifica a situação de um
aluno em uma matéria. Primeiro a instrução if verifica se a nota é menor igual a 5, se a analise retornar
true é apresentada e mensagem Reprovado. Se for retornado false será executada a próxima
verificação associada ao else if, se a nota é igual a 10 se o retorno for true será apresentada a mensagem
Aprovado com louvor senão será apresentada a mensagem Aprovado
double nota = 7.0;
if(nota <= 5.0){
print("Reprovado");
} else if (nota == 10.0) {
print("Aprovado com louvor");
} else {
print("Aprovado");
}
TÉCNICO EM INFORMÁTICA
4.5.2. Operador ternário
O operador ternário recebe três argumentos e é normalmente usado quando somente duas ações
são necessárias. O primeiro argumento é a expressão lógica a ser analisada, o segundo é a instrução a
ser executada se o retorno da expressão for true e o terceiro é a instrução a ser executada se o retorno da
expressão for false.
EXPRESSÃO LÓGICA TRUE FALSE
nota >= 5.0 ? print("Aprovado") : print("Reprovado")
4.5.3. switch - case
A instrução switch avalia o valor de uma variável inteira ou string comparando com os valores
apresentados nas clausulas case. Se o valor armazenado na variável for compatível com algum case, o
conjunto de instruções associados ao mesmo é executado. Se não houver nenhum case compatível é
executado o bloco de instruções associados a clausula default.
As seguintes regras se aplicam a instrução switch:
 Pode haver qualquer número de clausulas case em um switch;
 As clausulas case podem utilizar somente valores constantes. Não pode ser usadas
variáveis ou expressões lógicas;
 O tipo de dados da variável utilizado nas clausulas case tem que ser o mesmo da variável
analisado pelo switch;
 Se não colocar a instrução break em cada bloco o fluxo de execução continuará mesmo que
a opção correta tenha sido encontrada.
 Cada clausula case deve ter um valor único;
 A clausula default é opcional.
TÉCNICO EM INFORMÁTICA
Exemplo switch…case
void main() {
var nota = "A";
switch(nota) {
case "A":
print("Excelente");
print("Aprovado");
break;
case "B":
print("Bom");
print("Aprovado");
break;
case "C":
print("Regular");
print("Aprovado");
break;
case "D":
print("Insatisfatório");
print("Reprovado");
break;
case "E":
print("Insatisfatório");
print("Reprovado");
break;
default:
print("Nota inválida");
break;
}
}
TÉCNICO EM INFORMÁTICA
4.5.4. Loop for
A instrução for permite a iteração com uma lista de valores. Os valores são obtidos restringindo o
número de iterações pelo tamanho do objeto list. Outra forma de execução é determinar um valor inicial,
um valor final e um valor de passo para o loop for. Usar uma lista de valores também permite o uso do
for-in como uma iteração. A classe Iteration precisa ser do tipo Iterável (uma coleção de valores), e a
classe List é deste tipo. Ao contrário do loop for padrão o for-in itera por todos os objetos do List, expondo
os valores de propriedades de cada objeto.
Vamos dar uma olhada em dois exemplos mostrando como usar o loop for padrão e o loop for-in.
No primeiro exemplo, será utilizado o loop for padrão iterando em um list de valores string com a variável
listaFiltros. O loop for padrão recebe três parâmetros.
 O primeiro parâmetro inicializa a variável do tipo int aqui chamada de i que contará cada
execução do loop.
 O segundo parâmetro controla quantas iterações serão executadas pelo loop. Para esse controle
executa-se a comparação do valor atual de (i) como o número total de iterações a serem
executadas.
 Uma vez que o índice do list inicia em zero a variável i tem que ter um valor menor que o tamanho
do list. Para se obter o número correto de iterações usa-se o tamanho do list (listaFiltros.length) -
1.
 O terceiro parâmetro incrementa o número de iterações executada pelo acréscimo da variável i a
cada loop. Dentro do loop a instrução print é utilizada para mostrar cada valor do list listaFiltros.
// Loop for padrão
List listaFiltros = ['compania', 'cidade', 'estado'];
for (int i = 0; i < listaFiltros.length; i++) {
print('listaFiltros: ${listaFiltros[i]}');
}
// resultado da instrução print
// listaFiltros: compania
// listaFiltros: cidade
// listaFiltros: estado
No exemplo a seguir será utilizado o loop for-in para iterar com valores da variável list
listaNumeros a qual possui uma lista de números inteiros. O loop for-in recebe um parâmetro que
apresenta as propriedade do objeto listaNumeros. Foi declarada uma variável do tipo int numero para
acessar as propriedade do objeto List listaNumeros. No interior do loop, a instrução print é usada para
mostrar cada valor da listaNumeros utilizando o valor da variável numero.
TÉCNICO EM INFORMÁTICA
// loop for-inList listaNumberos = [10, 20, 30];
for (int numero in listaNumberos) {
print('número: $numero');
}
// Resultado da instrução print
// número: 10
// número: 20
// número: 30
4.5.5. Loop while e do-while
Ambos os loops while e do-while avaliam uma condição e executam iterações enquanto a
condição retorna um valor true. O loop while avalia a condição antes da iteração ser executada. Já o loop
do-while avalia a condição depois que a iteração é executada pelo menos uma vez. Vamos observar dois
exemplos que mostram como usar os loops while e do-while.
O primeiro exemplo funciona da seguinte forma, enquanto a condição definida for verdadeira, o
conjunto de instruções do loop é executado. Geralmente é utilizado quando não se sabe quantas vezes
irá repetir o conjunto de instruções.
int j = 0;
bool sair = “n”;
while(j < 10){
print(j); // Mostra de 0 a 9
j++;
}
No segundo, diferente do while que avalia a condição antes do loop, o do-while executa o conjunto
de instruções do loop e depois avalia a condição. Se a analise retornar true é iniciada uma nova iteração.
Este ciclo se repete até que a avaliação da condição se torne false.
int k = 0;
do {
print(k);
k++;
} while (k < 10);
TÉCNICO EM INFORMÁTICA
4.5.6. while e break
Usar a instrução break permite parar um loop pela avaliação de uma condição na iteração.
var i = 1;
while (i <= 10) {
if (i % 5 == 0) {
print("O primeiro multiplo de 5 entre 1 e 10 é : ${i}");
break;
//sai do loop quando o primeiro múltiplo é encontrado
}
i++;
}
4.5.7. continue
Usando a instrução continue, é possível parar no local atual da iteração e pular para o início do
próxima iteração do loop. No exemplo o loop for percorre uma lista de números de 10 a 80. Dentro do loop
uma instrução if verifica quando o número é menor que 30 e maior que 50, e se a condição é encontrada,
a instrução continue para a iteração corrente e começa a próxima. Usando a instrução print, será
apresentado somente os número 30, 40 e 50.
// Continue - pula para a próxima iteração do loop
List listaNumeros = [10, 20, 30, 40, 50, 60, 70, 80];
for (int numero in listaNumeros) {
if (numero < 30 || numero > 50) {
continue;
}
print('nmero: $numero'); // Serão apresentados os números 30, 40, 50
}
4.6. Usando funções
Funções são usadas para agrupar trechos de código que serão utilizados em vários pontos da
programação. Uma função pode opcionalmente receber parâmetros e retornar valores. Em razão do Dart
ser uma linguagem orientado a objeto, funções podem ser atribuídas a variáveis ou passadas como
argumento para outras funções. Se um função executa uma única instrução, pode-se utilizar a sintaxe
seta (=>). Toda função retorna um valor padrão e se a instrução return não é especificada, o Dart
automaticamente adiciona implicitamente no corpo da função uma instrução return null.
Uma vez que toda função retorna um valor, inicia-se a construção com a especificação do tipo de
retorno que é esperado. Quando chama a função e nenhum valor de retorno é esperado, inicie a
declaração da função o tipo void que significa nenhum retorno. Usar o tipo void na declaração da função
não é obrigatório em Dart já que a linguagem faz isso implicitamente quando uma função não tem retorno,
mas é recomendada a pratica de declarar o void por uma questão de legibilidade de código. Mas quando
TÉCNICO EM INFORMÁTICA
é esperado um retorno de um valor inicie a declaração da função com o tipo de dado que será retornado
(bool, int, String, List. . .) e use a instrução return para retornar o valor.
Sintaxe
TipoDeRetorno nomeDaFuncao(TipoDoArgumento nomeDoArgumento, OutroTipo outroNomeDeArgumento){
// Aqui vai o corpo da função
return tipoDeRetorn;
}
Exemplos
void main() {
int multiplicacao(int valor1, int valor2) {
return (valor1 * valor2);
}
print(multiplicacao(4, 3));
}
Quando se tem uma função com uma única instrução pode-se declara-la utilizando a sintaxe de seta
void main() {
int multiplicacao(int valor1, int valor2) => (valor1 * valor2);
print(multiplicacao(2, 3));
}
Quando se tem uma função que somente chama outra função pode-se utiliza a sintaxe de seta para a
chamada.
void multiplicacao(int valor1, int valor2) => print(valor1 * valor2);
void main() => multiplicacao(10, 3);
Algumas vezes criamos funções que podem ou não precisar de alguns argumentos e em Dart você pode
definir que os argumentos podem ser opcionais e se necessário definir valores padrão para o argumento
caso nenhum valor seja definido na chamada da função.
Tem duas formas de fazer isso:
4.6.1. Parâmetros nomeados opcional
Como o nome sugere, os parâmetros tem nomes e para passar algum valor para o parâmetro nomeado
que é opcional é preciso indicar para qual parâmetro é aquele valor e a sintaxe é muito simples
nomeDoParam: valor, outroParam: outroValor
TÉCNICO EM INFORMÁTICA
Exemplo
void exemploParametroNomeadoOpcional
(String msg/*Parâmetro obrigatorio*/,{String nome, String sobrenome /*Parâmetros opcionais*/}){
print('$nome $sobrenome: $msg');
}
main(){
exemploParametroNomeadoOpcional("Olá viajante!");
exemploParametroNomeadoOpcional("Olá!", nome: "João", sobrenome: "da Silva");
exemploParametroNomeadoOpcional("Olá!", sobrenome: "Maria", nome: "José");
}
4.6.2. Parâmetros posicionados opcional
Muito parecido com os parâmetros nomeados que você pode declarar em qualquer ordem desde que
indique o nome do parâmetro que o valor será atribuído, os parâmetros posicionados tem que seguir a
ordem exata que foram declarados na função.
Exemplo
void funcaoParametroPosicionadoOpcional
(String msg/*Parâmetro obrigatorio*/,[String nome, String sobrenome /*Parâmetros opcionais*/]){
print('$nome $sobrenome: $msg');
}
main(){
funcaoParametroPosicionadoOpcional("Olá viajante!");
funcaoParametroPosicionadoOpcional("Olá!", "Wilton","Jr");
}
4.6.3. A função main
Você deve ter reparados em alguns exemplos o uso da função main(){} ela é o ponto de partida
quando um app ou um script Dart é executado.
A função main ela retorna nulo e pode receber uma lista de String como parâmetro para quando
você for usar o cmd ou terminal para executar algum app/script Dart o que for digitado vai ser passado
como List<String> a partir dai é só tratar cada String .
main(List<String> args){
print(args)
}
TÉCNICO EM INFORMÁTICA
4.7. Importação de pacotes
Para usar um pacote externo, biblioteca ou uma classe externa, usa-se a instrução import. A
separação da lógica do código em diferentes arquivos de classe permite que você separe e agrupe o
código em objetos gerenciáveis. A instrução import permite o acesso a pacotes, classes e bibliotecas
externas. Necessita somente um argumento que especifica a uniform resource identifier (URI) ou em
português identificador uniforme de recurso da classe ou biblioteca. Se a biblioteca é criada pelo
gerenciador de pacotes então é necessário especificar a diretiva “package:” antes do URI. Ao importar
uma classe, você especifica o local e o nome da classe ou package: diretiva.
// Importando o pacote material
import 'package:flutter/material.dart';
// Importando um classe externa
import 'charts.dart';
// Importando uma classe externa de uma pasta diferente
import 'services/charts_api.dart';
// Importando uma classe externa com package: diretiva
import 'package:project_name/services/charts_api.dart';
4.8. Usando Classes
Dart é uma linguagem orientada a objetos com classes e herança baseada em mixin. Todo objeto
é uma instância de uma classe e todas descendem de Object. A herança baseada em mixin significa que,
embora toda classe (exceto Object) tenha exatamente uma superclasse, um corpo de classe pode ser
reutilizado em várias hierarquias de classe. Os métodos são uma maneira de adicionar funcionalidade a
uma classe sem alterar a classe ou criar uma subclasse.
TÉCNICO EM INFORMÁTICA
4.8.1. Usando membros da classe
Os objetos têm membros que consistem em funções e dados (métodos e variáveis de instância ,
respectivamente). Quando você chama um método, invoca-o em um objeto: o métodotem acesso às
funções e dados desse objeto. Use um ponto ( .) para se referir a uma variável ou método de instância:
class Pessoa {
String nome;
int idade;
double altura;
void dormir(){
print("$nome está dormindo");
}
void aniver(){
idade++;
}
}
void main(){
Pessoa pessoa1 = new Pessoa();
pessoa1.nome = "Diego";
pessoa1.altura = 1.70;
pessoa1.idade = 30;
print(pessoa1.nome);
pessoa1.aniver();
print(pessoa1.idade);
}
4.8.2. Usando construtores
Pode-se criar um objeto usando construtor. O nome do construtor pode ser o nomeClasse() ou
nomeClasse.Identificador(). No primeiro exemplo é criada uma classe Pessoa que utiliza o construtor
Pessoa(), já no segundo exemplo utiliza-se o construtor Pessoa.individuo()
TÉCNICO EM INFORMÁTICA
Exemplo 1.
class Pessoa {
String nome;
int idade;
double altura;
Pessoa(this.nome, this.altura, this.idade);
void dormir(){
print("$nome está dormindo");
}
void aniver(){
idade++;
}
}
void main() {
var pessoa = Pessoa("João", 1.80, 33);
pessoa.dormir();
}
Exemplo 2.
class Pessoa {
String nome;
int idade;
double altura;
Pessoa.individuo(this.nome, this.altura, this.idade);
void dormir(){
print("$nome está dormindo");
}
void aniver(){
idade++;
}
}
void main() {
var pessoa = Pessoa.individuo("João", 1.80, 33);
pessoa.dormir();
}
TÉCNICO EM INFORMÁTICA
4.8.3. Herança
Dart possui herança simples
class Animal {
String nome;
double peso;
Animal(this.nome, this.peso);
void comer() {
print("$nome comeu");
}
void fazerSom() {
print("$nome fez dom!");
}
}
class Cachorro extends Animal {
int fofura;
Cachorro(this.fofura, String nome, double peso) : super(nome, peso);
void brincar() {
fofura += 10;
print("fofura do $nome aumentou para $fofura");
}
}
class Gato extends Animal {
Gato(String nome, double peso) : super(nome, peso);
bool estaAmigavel() {
return true;
}
}
TÉCNICO EM INFORMÁTICA
4.8.4. Mixins
Os Mixins permitem com que você adicione métodos de outras classes em sua classe sem utilizar
herança. Vamos criar uma classe para podermos entender melhor:
void main(){
Carro c1 = Carro("Fusca");
c1.acelerar(100);
}
class Carro extends Automovel {
String nome;
Carro(this.nome);
void acelerar(int velocidade) {
print("Acelerando com $velocidade km/h");
}
String toString(){
return nome;
}
}
abstract class Automovel {
void acelerar(int velocidade);
}
Agora vamos criar outra classe Combustível em que iremos criar um método abastecer:
class Combustivel{
abastacer(int qtde){
print("Abastecendo $qtde l")
}
}
TÉCNICO EM INFORMÁTICA
Como a classe Carro já foi herdada de automóvel, não pode ser herdada da classe de
Combustível então vamos utilizar o mixin:
class Carro extends Automovel with Combustivel {
String nome;
Carro(this.nome);
void acelerar(int velocidade) {
print("Acelerando com $velocidade km/h");
}
String toString(){
return nome;
}
}
class Combustivel{
abastacer(int qtde){
print("Abastecendo $qtde l")
}
}
abstract class Automovel {
void acelerar(int velocidade);
}
É como se o método abastecer fosse copiado para dentro da classe Carro. Sendo assim,
podemos agora incluir em main o método que fora adicionado:
void main(){
Carro c1 = Carro("Fusca");
c1.acelerar(100);
c1.abastecer(50);
}
Agora está tudo funcionando, porém, caso você queira acrescentar mais classes, você pode
utilizar uma vírgula e acrescentar a nova classe posteriormente:
class Carro extends Automovel with Combustivel, B, C, D {
String nome;
Carro(this.nome);
void acelerar(int velocidade) {
print("Acelerando com $velocidade km/h");
}
String toString(){
return nome;
}
}
TÉCNICO EM INFORMÁTICA
4.8.5. Classes Abstratas
Não é concreta, é só uma ideia, um conceito abstrato, uma classe genérica só tem um conteúdo
padrão que depois poderá ser implementado de uma forma concreta. Por exemplo, dentro de Animal
temos os felinos e pessoas, dentro de felinos gato e tigre que são concretos. Assim, vemos que as
classes abstratas são genéricas.
Usamos a palavra chave abstract para impedir que uma classe possa ser instanciada. Esse é o
efeito direto de se usar o modificador abstract na declaração de uma classe:
abstract class Animal {
String nome;
double peso;
Animal(this.nome, this.peso);
void comer(){
print("$nome comeu");
}
void fazerSom(){
print("$nome fez som!");
}
}
Pode-se também declarar métodos nas classes abstratas sem declarar nada, sem nenhum corpo,
ou seja, na parte void fazerSom() pode-se retirar o seu corpo, desta forma:
abstract class Animal {
String nome;
double peso;
Animal(this.nome, this.peso);
void comer(){
print("$nome comeu");
}
void fazerSom();
}
TÉCNICO EM INFORMÁTICA
E sempre que herda-las temos que implementar o método:
abstract class Animal {
String nome;
double peso;
Animal(this.nome, this.peso);
void comer(){
print("$nome comeu");
}
void fazerSom();
}
class Gato extends Animal {
Gato(String nome, double peso): super(nome, peso);
bool estaAmigavel(){
return true;
}
// Obrigado a implementá-lo
@override
void fazerSom(){
print("$nome fez miau!");
}
}
Agora vamos em declarar em main para ver o que ocorre:
main() {
var gato = Gato('Garfield', 0.30);
gato.fazerSom();
}
Irá mostrar 'Garfield fez miau!' no console, veja que implementamos o método fazerSom() da
classe abstrata no Gato.
TÉCNICO EM INFORMÁTICA
4.8.6. Interfaces
As interfaces definem um conjunto de métodos disponíveis em um objeto. O Dart não possui uma
sintaxe para declarar interfaces. As próprias declarações de classe são interfaces no Dart. As classes
devem usar a palavra-chave implements para poder usar uma interface. Quando qualquer classe
implementa uma Interface, ela deve redefinir todos os métodos e variáveis de instância da interface.
void main() {
Pais br = new Pais();
print("Nome país : ${br.nome()}");
}
class Pais implements PaisInfo {
String nome() {
return "Brasil";
}
String bandeira() {
return "Verde Amarelo";
}
}
class PaisInfo {
String nome(){}
String bandeira(){}
}
Dart não suporta múltiplas heranças, mas pode implementar múltiplas interfaces. Tal recurso
fornece o mesmo poder e funcionalidades da múltipla herança.
class nome implements interface1, interface2, interface3
TÉCNICO EM INFORMÁTICA
5. Criando AlertDialogs
Uma caixa de diálogo de alerta, AlertDialgos, informa o usuário sobre situações que exigem
reconhecimento. Um diálogo de alerta tem um título opcional e uma lista opcional de ações onde o título é
exibido acima do conteúdo e as ações são exibidas abaixo do conteúdo. Ele aparece como um pop-up no
meio da tela que coloca uma sobreposição sobre o fundo. É mais usado para confirmar uma das ações
irreversíveis do usuário.
A maneira mais simples de criar um diálogo de alerta é chamar a função showDialog() que altera o
estado da aplicação. Assim temos que definir a função showDialog() com um context e uma
função itemBuilder que precisa retornar um objeto do tipo Dialog, onde a opção mais comum é usar
um AlertDialog.
void _exibirDialogo() {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog();
},
);
}
Podemos ter muitas configurações para um AlertDialog, onde vários atributos podem ser definidos
incluindo o titulo contéudo e Actions ou ações. A Actions é o lugar onde você define os Buttons,
geralmente na parte inferior da caixa de diálogo. A seguir um trecho de código básico para definição de
um AlertDialog com um botão:
void _showDialog() {
showDialog(
context: context,
builder: (BuildContext context) {
// retorna um objeto do tipo Dialog
return AlertDialog(
title: new Text("Alert Dialog titulo"),
content: new Text("Alert Dialog body"),
actions: <Widget>[
// define os botões na base do dialogo
new FlatButton(
child: new Text("Fechar"),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
TÉCNICO EM INFORMÁTICA
5.1. Criando AlertDialogs
No Visual Studio Code tecle CTRL+ SHIFT+P para abrir a paleta de comandos e a seguir
selecione a opção : Fluter:New Project
A seguir informe o nome do projeto : flutter_alertdialogs e tecle ENTER.Na janela de diálogo a seguir selecione a pasta onde o projeto vai ser salvo e clique em: Select a
folder to create the project in.
O Flutter vai criar um projeto padrão onde todo o código da aplicação vai estar no
arquivo main.dart dentro da pasta lib do projeto.
TÉCNICO EM INFORMÁTICA
Vamos substituir o código do arquivo main.dart pelo código abaixo:
import 'package:flutter/material.dart';
import 'AlertDialogs/alerts.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'AlertDialog',
theme: ThemeData(
primarySwatch: Colors.blue,
),
debugShowCheckedModeBanner: false,
home: Home(),
);
}
}
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Alert Dialog"),
centerTitle: true,
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: RaisedButton(
child: Text('Exibir Alerta'),
onPressed: () {
showAlertDialog1(context);
},
),
),
);
}
}
Este será o nosso template onde temos um botão com o texto 'Exibir Alerta' que ao ser clicado
aciona o método onPressed() e chama o método showAlertDialog1(context) onde vamos definir o código
para criar os AlertDialog. Dentro da pasta lib do projeto, clique com o botão direito do mouse e crie uma
pasta chamada AlertDialogs e nesta nova, pasta clique com o botão direito do mouse e crie o arquivo
alerts.dart para definir o código de cada um dos AlertDialogs.
TÉCNICO EM INFORMÁTICA
5.1.1. Criando uma caixa de alerta com um botão
import 'package:flutter/material.dart';
showAlertDialog1(BuildContext context) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Promoção Imperdível"),
content: Text("Não perca a promoção."),
actions: [
FlatButton(
child: Text("OK"),
onPressed: () {
// fecha o AlertDialog
Navigator.of(context).pop();
},
),
],
);
},
);
}
TÉCNICO EM INFORMÁTICA
5.1.2. Criando uma caixa de alerta com dois botões
showAlertDialog2(BuildContext context) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Alert Dialog"),
content: Text("Deseja continuar aprendendo Flutter ?"),
actions: [
FlatButton(
child: Text("Cancelar"),
onPressed: () {
// fecha o AlertDialog
Navigator.of(context).pop();
},
),
FlatButton(
child: Text("Continar"),
onPressed: () {
// fecha o AlertDialog
Navigator.of(context).pop();
},
),
],
);
},
);
}
TÉCNICO EM INFORMÁTICA
5.1.3. Criando uma caixa de alerta com três botões
showAlertDialog3(BuildContext context) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Aviso"),
content: Text("Disparar este míssil vai destruir o mundo."),
actions: [
FlatButton(
child: Text("Lembrar"),
onPressed: () {
// fecha o AlertDialog
Navigator.of(context).pop();
},
),
FlatButton(
child: Text("Cancelar"),
onPressed: () {
// fecha o AlertDialog
Navigator.of(context).pop();
},
),
FlatButton(
child: Text("Disparar"),
onPressed: () {
// fecha o AlertDialog
Navigator.of(context).pop();
},
),
],
);
},
);
}
TÉCNICO EM INFORMÁTICA
5.2. RFlutter Alert
RFlutter Alert é alert/popup dialog customizável fácil de usar para Flutter. Você pode criar estilos
de alerta reutilizáveis ou adicionar botões quantas vezes quiser com facilidade
5.2.1. Recursos
 Uma linha básica para criação do alert
 Adição de botões dinamicamente
 Estilos de Alertas pré definidos (success, error, warning, info)
 Estilos de Alertas reutilizáveis
 Personalizável:
 Mudança de animação (fromTop, fromBottom, fromRight, fromLeft, grow, shrink)
 Configuração de tempo de animação
 Show/hide close button
 Definir toque de sobreposição para ignorar
 Atribuir estilos de título e descrição
 Alterar o estilo da borda da caixa de diálogo
5.2.2. Iniciando
Você deve adicionar a biblioteca como uma dependência no seu projeto no arquivo pubspec.yaml
dependencies:
rflutter_alert: ^1.0.3
Também é possível referenciar o repositório git se quiser:
dependencies:
rflutter_alert:
git: git://github.com/RatelHub/rflutter_alert.git
Depois de adicionar as dependências deve-se executar o comando:
flutter packages get
E no arquivo arquivo de implementação dos alerts deve-se fazer a importação do pacote:
import 'package:rflutter_alert/rflutter_alert.dart';
TÉCNICO EM INFORMÁTICA
5.2.3. Exemplo RFlutter Alert
No Visual Studio Code tecle CTRL+ SHIFT+P para abrir a paleta de comandos e a seguir
selecione a opção : Fluter:New Project
A seguir informe o nome do projeto : alert_rflutter e tecle ENTER.
Na janela de diálogo a seguir selecione a pasta onde o projeto vai ser salvo e clique em: Select a
folder to create the project in.
O Flutter vai criar um projeto padrão onde todo o código da aplicação vai estar no
arquivo main.dart dentro da pasta lib do projeto.
TÉCNICO EM INFORMÁTICA
Vamos substituir o código do arquivo main.dart pelo código abaixo:
import 'package:flutter/material.dart';
import 'package:alert_rflutter/alert/alerts.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'AlertDialog',
theme: ThemeData(
primarySwatch: Colors.blue,
),
debugShowCheckedModeBanner: false,
home: Home(),
);
}
}
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Alert Dialog"),
centerTitle: true,
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
child: Text('Alert Básico'),
onPressed: () => onBasicAlertPressed(context),
),
RaisedButton(
child: Text('Alert com Botão'),
onPressed: () => onAlertButtonPressed(context),
),
RaisedButton(
child: Text('Alert com vários Botões'),
onPressed: () => onAlertButtonsPressed(context),
),
RaisedButton(
child: Text('Alert utilizando Estilos'),
onPressed: () => onAlertWithStylePressed(context),
),
RaisedButton(
child: Text('Alert com imagem personalizada'),
onPressed: () => onAlertWithCustomImagePressed(context),
),
RaisedButton(
child: Text('Alert com conteúdo personalizado'),
onPressed: () => onAlertWithCustomContentPressed(context),
),
],
),
)
);
}
}
TÉCNICO EM INFORMÁTICA
Este será o nosso template no qual temos vários botões que ao serem clicados acionam os seus
métodos onPressed() e chamam o método associados a cada um deles. Neste métodos vamos definir o
código para criar os AlertDialog. Dentro da pasta lib do projeto, clique com o botão direito do mouse e crie
uma pasta chamada alert e nesta nova pasta vamos criar o arquivo alerts.dart para definir o código de
cada um dos AlertDialogs. Também criaremos uma pasta assets na raiz do projeto. E nesta pasta coloque
o arquivo success.png.
TÉCNICO EM INFORMÁTICA
Para usar um recurso como fontes e imagens é necessário inserir o mesmo no pubspec.yaml para
que a aplicação tenha acesso ao recurso. Para isso abra arquivo pubspec.yaml para inserir o recurso de
imagem
No arquivo alerts.dart insira o seguinte código:
import 'package:flutter/material.dart';
import 'package:rflutter_alert/rflutter_alert.dart';
Estes imports possibilitam o uso dos recursos da biblioteca material e da rflutter_alert. A seguir
serão apresentados os trechos de códigos com a imagem dos alert criado.
5.2.4. A maneira mais fácil de criar o alerta com RFlutter
onBasicAlertPressed(context) {
Alert(
context: context,
title: "RFLUTTER ALERT",
desc: "Flutter é mais impressionante com o RFlutter Alert.")
.show();
}
TÉCNICO EM INFORMÁTICA
5.2.5. Alert com único botão com RFlutter
onAlertButtonPressed(context) {
Alert(
context: context,
type: AlertType.error,
title: "RFLUTTER ALERT",
desc: "Flutter é mais impressionante com o RFlutter Alert.",buttons: [
DialogButton(
child: Text(
"LINDO",
style: TextStyle(color: Colors.white, fontSize: 20),
),
onPressed: () => Navigator.pop(context),
width: 120,
)
],
).show();
}
5.2.6. Alert com vários botões customizados RFlutter
onAlertButtonsPressed(context) {
Alert(
context: context,
type: AlertType.warning,
title: "RFLUTTER ALERT",
desc: "Flutter é mais impressionante com o RFlutter Alert.",
buttons: [
DialogButton(
child: Text(
"FLAT",
style: TextStyle(color: Colors.white, fontSize: 20),
),
onPressed: () => Navigator.pop(context),
color: Color.fromRGBO(0, 179, 134, 1.0),
),
DialogButton(
child: Text(
"GRADIENT",
style: TextStyle(color: Colors.white, fontSize: 20),
),
onPressed: () => Navigator.pop(context),
gradient: LinearGradient(colors: [
Color.fromRGBO(116, 116, 191, 1.0),
Color.fromRGBO(52, 138, 199, 1.0)
]),
)
],
).show();
}
TÉCNICO EM INFORMÁTICA
5.2.7. Uso avançado de alerts
onAlertWithStylePressed(context) {
// Estilo de alerta personalizado e reutilizável
var alertStyle = AlertStyle(
animationType: AnimationType.fromTop,
isCloseButton: false,
isOverlayTapDismiss: false,
descStyle: TextStyle(fontWeight: FontWeight.bold),
animationDuration: Duration(milliseconds: 400),
alertBorder: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0.0),
side: BorderSide(
color: Colors.grey,
),
),
titleStyle: TextStyle(
color: Colors.red,
),
constraints: BoxConstraints.expand(width: 300)
);
// Caixa de diálogo de alerta usando o estilo de alerta personalizado
Alert(
context: context,
style: alertStyle,
type: AlertType.info,
title: "RFLUTTER ALERT",
desc: "Flutter é mais impressionante com o RFlutter Alert.",
buttons: [
DialogButton(
child: Text(
"LINDO",
style: TextStyle(color: Colors.white, fontSize: 20),
),
onPressed: () => Navigator.pop(context),
color: Color.fromRGBO(0, 179, 134, 1.0),
radius: BorderRadius.circular(0.0),
),
],
).show();
}
TÉCNICO EM INFORMÁTICA
5.2.8. Alert personalizado com imagem
onAlertWithCustomImagePressed(context) {
Alert(
context: context,
title: "RFLUTTER ALERT",
desc: "Flutter é mais impressionante com o RFlutter Alert.",
image: Image.asset("assets/success.png"),
).show();
}
5.2.9. Alert com conteúdo personalizado
onAlertWithCustomContentPressed(context) {
Alert(
context: context,
title: "LOGIN",
content: Column(
children: <Widget>[
TextField(
decoration: InputDecoration(
icon: Icon(Icons.account_circle),
labelText: 'Username',
),
),
TextField(
obscureText: true,
decoration: InputDecoration(
icon: Icon(Icons.lock),
labelText: 'Password',
),
),
],
),
buttons: [
DialogButton(
onPressed: () => Navigator.pop(context),
child: Text(
"LOGIN",
style: TextStyle(color: Colors.white, fontSize: 20),
),
)
]).show();
}
TÉCNICO EM INFORMÁTICA
6. Push notification
Push notification é uma notificação que o usuário recebe em um aplicativo de smartphone, tablet
ou em um navegador sem requisitá-la. Ao analisar o seu significado, fica mais fácil compreender.
Enquanto notification é, obviamente, "notificação" em inglês, push é um falso cognato, pois soa
parecido com "puxar", mas na realidade significa "empurrar". A tradução sugere, então, que a push
notification é uma notificação que é empurrada ao usuário. Mas na prática não é bem assim. Isso porque
ela só é enviada se o usuário, em algum momento, demonstrar interesse no conteúdo veiculado pela
marca. No caso dos tablets e smartphones, esse interesse é o download do aplicativo que envia as push
notifications.
E no navegador? É quando o usuário acessa um site que abre uma espécie de popup com uma
pergunta como "Você deseja receber notificações?".
Então, as push notifications só vão aparecer para quem permitir. Além disso, quem fica
incomodado pode, geralmente, ficar com o aplicativo e desativar as notificações nas configurações do app.
No navegador, isso também pode ser feito na seção de configurações.
Por tudo isso, a push notification é muito menos invasiva que o SMS (Short Message Service), por
exemplo. Também conhecido como torpedo, o SMS é a velha mensagem de texto enviada para o celular.
Muitas empresas ainda utilizam essa forma de se comunicar com os clientes, às vezes, sem que eles
tenham manifestado o interesse em receber as informações enviadas.
6.1. Como o push notification funciona?
Todo smartphone e tablet tem uma seção que lista as notificações recebidas. Isso porque os
desenvolvedores dos principais sistemas operacionais (Apple, Google, Windows e Blackberry) possuem
um serviço OSPNS, que permite o envio das mensagens.
TÉCNICO EM INFORMÁTICA
Nos smartphones com sistema Android, por exemplo, elas aparecem na tela bloqueada ou,
quando desbloqueada, ao puxar o menu de opções da barra na parte de cima da tela. São essas as
notificações que chamamos de push notifications. Quando chega uma nova, surge um popup na tela, que
pode vir acompanhado de um som e de uma rápida vibração para chamar a atenção do usuário.
Quando o usuário toca na push notification, ele é levado ao aplicativo que a enviou. Para uma
marca se comunicar dessa maneira com um usuário, além de desenvolver um aplicativo, precisa de um
servidor e de um software de envio de push notification, caso a empresa não possua tecnologia própria
para isso.
No caso das notificações que aparecem no navegador, a mensagem surge em um dos cantos da
tela, com a opção de fechá-la (clicando no X) ou de clicar na mensagem e acessar o site do conteúdo que
despertou o interesse.
6.2. Quais são as possibilidades de uso?
Os conteúdos das mensagens enviadas via push notification podem ser dos mais variados. Vai
depender muito do que a empresa faz ou do que aplicativo oferece, além da criatividade do
desenvolvedor, é claro.
O mais evidente é para informar sobre promoções em lojas virtuais. Por exemplo, você tem um
aplicativo com e-commerce que vende sapatos e faz um dia promocional com frete grátis para compras
acima de R$ 150.
A melhor maneira de comunicar essa novidade aos clientes é enviando um push notification. A
chegada de novos produtos e coleções também é um bom motivo para enviar notificações. E também há
mensagens personalizadas, com base na própria atividade do usuário. Por exemplo, se ele fez uma
compra via aplicativo, ele pode receber uma push notification informando que o produto foi enviado.
Em aplicativos que fazem a mediação entre duas pontas na compra de produtos ou serviços, as
notificações servem para avisar ao vendedor quando há uma venda ou interesse de um possível
comprador, e ao comprador quando o vendedor respondeu sua dúvida. Se você anuncia um imóvel para
alugar no Airbnb, por exemplo, o aplicativo do serviço lhe envia um push notification quando um usuário
realiza uma reserva.
Enfim, poderíamos listar infinitas outras possibilidades. Mas é mais prático recomendar que você
identifique o público-alvo e pense nas mensagens de acordo com o seu interesse.Que tipo de novidade o
usuário que baixou seu aplicativo gostaria de ver?
TÉCNICO EM INFORMÁTICA
6.3. Quais são as possibilidades de uso?
Neste exemplo será apresentada uma forma mais descomplicada ainda de enviar push
notifications. Uma das tecnologias mais usada para envio de push é o firebase, devido a sua alta
integração com o Flutter. Para gerenciar os envios dos push utilizaremos a plataforma OneSignal
(https://onesignal.com) que é apresentada na figura ??
Figura ?? Página inicial do https://onesignal.com
O OneSignal é uma plataforma que se comunica com o firebase para fazer o push, nele é possível
ainda utilizar o crashlytics. Neste exemplo faremos a comunicação do OneSignal com um App
desenvolvido em Flutter.
6.4. Criando uma conta no OneSignal
Acesse o site https://onesignal.com e clique em Sign Up para acessar a tela inicial de cadastro
apresentada na Figura??
Figura ?? Tela inicial de cadastro do site https://onesignal.com
TÉCNICO EM INFORMÁTICA
É possível fazer o cadastro no site utilizando um email pessoal ou utilizando contas do GitHub,
Google ou Facebook. Após o processo de cadastro será envidadoum email de validação para a conta de
email informada, conforme mostrado na Figura ??
Figura ?? Email de confirmação de cadastro enviado pelo OneSignal
TÉCNICO EM INFORMÁTICA
6.5. Criando uma conta no Firebase
O Firebase é um Baas (Backend as a Service) para aplicações Web e Mobile do Google, foi
lançado em 2004 e com o passar dos anos cresceu muito, se tornando uma ferramenta que hoje para
alguns projetos é a melhor opção, devido a quantidade de serviços oferecidos por ele, além da facilidade
de implementação.
BaaS ou BackEnd As A Service (MBaaS = Mobile BackEnd As A Service) é um serviço
disponibilizado em que toda a estrutura do backend como: configuração de servidor, integração com
banco de dados, sistema de push notification e outros serviços, que fazem parte do backend, estão
completamente prontos para se integrar com o seu aplicativo.
Após criar a conta no OneSignal precisamos criar um conta no Firebase ou usar a sua existente.
Como o Firebase é uma ferramenta Google, por padrão todo usuário tem acesso a recursos básicos da
ferramenta. Acessando https://firebase.google.com terá acesso a página inicial do firebase conforme
apresentado na Figura ??
Figura ?? Página inicial do https://firebase.google.com
6.6. Integrando o Firebase com o OneSignal
Agora com as duas contas criadas, vamos criar um app no Firebase e outro no OneSignal. Acesse
o console do Firebase clicando no botão ir para console da página inicial na página apresentada na
Figura ?? clique no botão Criar projeto
TÉCNICO EM INFORMÁTICA
Figura ?? Página inicial para criação de projeto
Na próxima página informe o nome do projeto e selecione a opção de aceitação dos termos de uso
do Firebase conforme apresentado na Figura ??
Figura ?? Passos iniciais para criação de projeto
Na próxima página apresentada na Figura ?? é possível ativar as ferramentas Analytics do Google
para o projeto
TÉCNICO EM INFORMÁTICA
Figura ?? Página de habilitação do Google Analytics para o projeto
Na próxima página apresentada na Figura ?? é informada a localização do Analytics, efetuada a
configuração padrão e a aceitação dos termos de uso e confidencialidade dos dados levantados pela
Google.
Figura ?? Página configuração de localização dos dados e termo de confidencialidade
TÉCNICO EM INFORMÁTICA
Projeto criado, vamos acessar a parte de configurações e navegar para Cloud Messaging. Para
isso no item Visão Geral do Projeto, clique no ícone da engrenagem e depois em configurações do projeto
conforme apresentado na Figura??
Figura ?? Acesso as configurações do projeto
Na Na configuração do projeto acessaremos a aba Cloud Messaging para obter a Chave do
servidor e o código do remetente necessários para a criação do app no OneSignal. A Figura ?? apresenta
a aba Cloud Messaging que contém a Chave do servidor e o código do remetente que copiaremos para o
projeto do app no OneSignal
Figura ?? Aba Cloud Messaging das configurações do projeto no Firebase
TÉCNICO EM INFORMÁTICA
6.7. Criando um App no OneSignal
Após criarmos no Firebase, vamos criar o App no OneSignal. Para isso faça login no site do
OneSignal conforme apresentado na Figura ??
Figura ?? Página de login no OneSignal
Ao logar no OneSignal, se não possuir nenhum App, será apresentada a tela inicial para criação
de um website ou app. Coloque um nome de sua preferência, lembrando que não se pode usar caracteres
especiais e espaço em branco no nome. Selecione em seguida a plataforma Android e clique no botão
Next: Configure Your Plataform conforme mostrado na Figura??.
Figura ?? Tela inicial de criação de app no OneSignal
TÉCNICO EM INFORMÁTICA
A tela apresentada na Figura ?? solicita a chave do servidor e o Código do usuário do projeto
criado anteriormente no Firebase. Estes dados conforme mencionado anteriormente se encontram em
configurações de projeto / Cloud Messaging
Figura ?? Tela Configure Platform do OneSignal e Cloud Messaging do Firebase
Pressione next e na próxima tela mostrada na Figura ?? escolha Native Android.
Figura ?? Página de seleção da Plataforma
TÉCNICO EM INFORMÁTICA
Ao pressionar o botão next será exibida a tela apresentada na Figura ??. Guarde o Your App ID
que será utilizado como parâmetro na programação Flutter.
Figura ?? Página de finalização de configuração do App.
Your App ID será a key usada no seu app flutter para identificar seu aplicativo. Então deixe isso
aberto no navegador pois iremos utilizar. Concluímos as configurações básicas, agora iremos colocar a
mão na massa, com o aplicativo. Daqui em diante fica a sua escolha, de criar um app novo ou usar em um
projeto existente.
Abra o vs code e crie um projeto flutter com o nome onesignal_notification. Para isso pressione as
teclas Ctrl+Shift+P, escolha flutter project conforme apresentado na Figura ??
Figura ?? Tela inicial de criação de Projeto Flutter no VS Code.
TÉCNICO EM INFORMÁTICA
Após clicar em Flutter Projetc será exibida a tela apresentada na Figura ??. Informe o nome do
projeto, no nosso caso onesignal_notification. Lembre-se nomes de projetos em Flutter não podem
possuir letras maiúsculas, espaços em branco e caracteres especiais.
Figura ?? Tela de criação de projeto Flutter no VS Code
Após criar o projeto será exibida uma tela conforme apresentado na Figura?? que solicita a
indicação da localização de armazenamento de todos os recursos e códigos
Figura ?? Janela para seleção de local para criação de pasta de projeto
TÉCNICO EM INFORMÁTICA
Agora com nosso projeto criado no vs code, conforme apresentado na Figura ??, iremos abrir o
arquivo pubspec.yam que é rum arquivo de metadados responsável por gerenciar as dependências do
projeto como bibliotecas e pacotes. Os pacotes existentes permitem muitos casos de uso, por exemplo,
solicitações de rede http , navegação personalizada / tratamento de rotas, integração com APIs de
dispositivos (url_launcher e battery) e uso de SDKs de plataformas de terceiros como Firebase
(FlutterFire).
Figura ?? Estrutura do arquivo principal do projeto criado.
TÉCNICO EM INFORMÁTICA
No arquivo pubspec.yam apresentado na Figura ?? acrescentaremos o pacote onesignal_flutter
para que a aplicação possa utilizar os recursos do OneSignal. Abaixo temos parte do código
Agora precisamos configurar os arquivos do android. Primeiro abra o arquivo build.gradle
apresentado na Figura ??, localizado em: android/build.gradle
Figura ?? Arquivo build.gradle
TÉCNICO EM INFORMÁTICA
Vamos adicionar a seguinte linha:
Em repositories
repositories {
// ...
// Gradle Plugin Portal
maven { url 'https://plugins.gradle.org/m2/' }
}
Já em dependencies
dependencies {
// ...
// OneSignal-Gradle-Plugin
classpath 'gradle.plugin.com.onesignal:onesignal-gradle-plugin:[0.12.1, 0.99.99]'
}
O resultado da modificação é apresentado na Figura ??
Figura ?? Arquivo build.gradle modificado
TÉCNICO EM INFORMÁTICA
Agora vamos em outro arquivo build.gradle, localizado em: android/app/build.gradle e no final dele
iremos colar a seguinte linha:
apply plugin: 'com.onesignal.androidsdk.onesignal-gradle-plugin
A Figura ?? apresenta o build.gradle, localizado em: android/app/build.gradle já modificado
Figura ?? Arquivo build.gradle modificado
Pronto! Temos tudo configurado para receber o código no flutter para inicializar o OneSignal. Agora
vamos para o código no Flutter. Iremos criar a estrutura de pastas e arquivos conforme apresentado na
Figura ??:
Figura ?? Estrutura de arquivos
TÉCNICO EM INFORMÁTICA
Nossa arquivo main.dart ficou da seguinte forma:
import 'package:flutter/material.dart';
import 'Pages/home/bloc/home_page.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter One Signal',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: HomePage(),
);
}
}
e nossa pages/home/home_page.dart
import 'package:flutter/material.dart';
class

Outros materiais