Boas vindas!
Sou o instrutor Alex Felipe, e este é o curso de Persistência de Dados Internos em Flutter.
Para que possamos evoluir nossas habilidades, absorver o conteúdo integral e ter o melhor aproveitamento possível, é importante já ter todos os conhecimentos apresentados nas aulas de Fundamentos de Flutter aqui da Plataforma Alura. Com este pré-requisito, entenderemos bem o que será visto ao longo deste curso.
Sobre o projeto, faremos a implementação oficial do aplicativo da Bytebank, começando pela tela inicial ou dashboard, diferente do que fizemos anteriormente ao implementarmos somente as transferências.
Nesta tela, vemos dois componentes visuais: o logotipo da empresa em maior evidência e um retângulo que representa a funcionalidade de contatos. Ao clicar nesta última, acessaremos a lista e poderemos cadastrar um novo item com o formulário através do floating action button. Simularemos um cadastro inserindo o nome "Joao" no campo "Full name" e um número de conta fictício "4000" em "Account number", finalizando a tarefa com clique no botão "Create".
Este é o fluxo do nosso aplicativo; observando brevemente, não há muitas novidades visuais em relação ao que já aprendemos, mas há detalhes extras importantes que serão explorados ao longo das aulas.
No curso anterior, quando salvávamos uma informação e esta era apresentada na lista, a perdíamos quando o aplicativo era reiniciado ou fechado. Agora, aprenderemos como estes dados são armazenados no dispositivo de modo a mantê-los no app mesmo após ter sido encerrado.
Conheceremos as possibilidades para armazenar esse tipo de informação e usaremos o plugin SQFlite, o qual fornece suporte ao banco de dados SQLite por debaixo dos panos.
Aprenderemos a adicionar dependências, realizar as configurações iniciais e trabalhar com processamentos assíncronos não apenas com Future
, mas também com async/await
, uma alternativa de syntactic sugar
("açúcar sintático") do Future. Veremos também algumas peculiaridades nas implementações de telas, como no caso da apresentação de lista.
Diferentemente do treinamento anterior, aprenderemos que nossa tela não necessariamente precisa ser um Stateful Widget
por completo para permitir a atualização de uma parte dela, algo que é possível com o FutureBuilder
.
Aprenderemos várias técnicas com base na criação de um fluxo completo utilizando boas práticas, refatoração de código e assim por diante. Serão muitos desafios durante o curso, então mãos à obra!
Agora que entendemos bem a necessidade do cliente, podemos começar a criar o projeto do novo aplicativo oficial da Bytebank. Essa criação será feita no IntelliJ IDEA, ainda que também seja possível fazê-la na Prompt de Comando, como demonstramos no treinamento anterior. Na tela inicial do IntellIJ, clicaremos na opção inicial de "Creat New Project" para gerar um novo projeto.
Teremos diversas opções na lista lateral da nova janela, entre elas a "Flutter", que usaremos para preparar o ambiente necessário para nosso desenvolvimento. No campo "Flutter SDK path:" mostramos onde está o SDK do Flutter dentro da máquina, o que depende de onde ele foi instalado. Após preenchermos de acordo com o local da instalação, clicaremos em "Next".
Na próxima tela, precisaremos preencher os campos com as informações do projeto. No primeiro campo "Project name", vamos inserir o nome "Bytebank". Nesse momento devemos prestar atenção, pois o Flutter utiliza a linguagem Dart, cujo padrão exige que sempre iniciemos os nomes em minúsculo. Sendo assim, se colocarmos o nome "Bytebank" com B maiúsculo e tentarmos finalizar a criação, o programa exibirá uma mensagem informando que o nome do módulo é inválido. Portanto, chamaremos o projeto de"bytebank".
O próximo passo será definir o caminho no campo "Project location" com o diretório onde desejamos salvar o projeto. Já no campo "Description", estamos livres para adicionar a descrição que quisermos, como "A new Bytebank project", ou até mesmo deixá-lo em branco.
O campo seguinte, "Project type", pede a escolha do tipo de projeto a ser realizado, que no nosso caso será "Application". As demais opções servem para o desenvolvimento de algum tipo de biblioteca a ser reutilizada em outros trabalhos, por exemplo.
Logo em seguida, há a opção "Use AndroidX artifacts", que poderá ser marcada com um check para mantermos os novos artefatos da plataforma do Android. A opção "Organization", por padrão, vem marcada como "com.example", mas é necessário inserir uma organização própria. Em nosso caso, desenvolveremos para a organização alura.com.br, então escrevemos "br.com.alura", exatamente da maneira inversa ao domínio da Alura. Se você tiver um domínio, também poderá utilizá-lo seguindo essa orientação.
Em seguida, poderemos definir as linguagens que, por padrão já, estão definidas como "Kotlin" e "Swift" para as plataformas Android e iOS, respectivamente. Poderemos manter assim justamente porque não alteraremos o código, mas se em outra situação a equipe quiser manter uma linguagem específica, é possível escolher outras opções.
Esses são os campos que precisamos preencher para criarmos o projeto. As demais informações, como "Create project offline" (para evitar a necessidade de baixar dependências), são adicionais e não teremos que nos preocupar com elas no momento. Ao clicarmos em "Finish", o IntelliJ IDE começará a baixar as dependências e a configurar os arquivos para uma melhor indexação. Se ocorrer algum problema, seremos informados por meio de feedbacks.
Com tudo funcionando adequadamente e sem mensagens de erro, iniciaremos o emulador, o que é o primeiro passo para a execução do aplicativo. É possível usar o emulador criado no treinamento anterior ou qualquer um que preferir, pois não há uma restrição sobre qual exatamente deve ser usado ou quais configurações específicas ele deve ter. Mas é recomendável utilizar pelo menos a mesma versão de Android, nesse caso o "Android Emulator Pixel 2XL API 28" ou Android 9 Pie, para termos a mesma visualização ao decorrer do curso.
Após a seleção do emulador, executaremos o aplicativo clicando no botão de "play" ao lado de main.dart
ou por meio do atalho "Shift + F10". O aspecto visual inicialmente será o mesmo do projeto de demonstração feito no Prompt de Comando no curso anterior, seguindo o sample padrão criado quando geramos um projeto em Flutter, algo que poderá ser modificado no futuro conforme a evolução dessa ferramenta.
Finalizada a execução, o projeto inicial do Flutter - um contador de cliques em um botão - será exibido no emulador. O próximo passo será limparmos o projeto e prepararmos o ambiente para escrevermos nosso próprio código. Primeiro, limparemos todo o retorno (return
) da classe MyApp
. Após isso, alteraremos o nome do widget inicial de MyApp
para BytebankApp
.
Para prepararmos a primeira tela, retornaremos um MaterialApp()
(do pacote material.dart
), da mesma forma que no curso anterior, e incluiremos alguns widgets de modo a termos uma visualização. Começaremos com a propriedade home
, que receberá o widget Scaffold()
, no qual teremos a capacidade de colocar uma AppBar()
contendo um title
com o widget Text()
. Nele, passaremos o texto "Dashboard".
import 'package:flutter/material.dart';
void main() => runApp(BytebankApp());
class BytebankApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Dashboard'),
),
), //Scaffold
); //MaterialApp
}
}
Se executarmos o código com um Hot reload ("Ctrl + "), receberemos uma tela de erro, justamente por termos feito modificações muito significativas. Sendo assim, faremos um Hot restart ("Shift + F10"), e a tela inicial será exibida com sucesso.
Essa primeira configuração é um preparo para executarmos os próximos passos da proposta de implementação, disponibilizada neste link.
Agora que conseguimos criar todo o ambiente para nosso projeto, começaremos a implementação da primeira tela que representará o Dashboard. Nela teremos dois elementos, ou seja, dois widgets, e começaremos com o Column()
- que, como aprendemos anteriormente, empilha outros elementos.
No IntelliJ, formataremos a definição da AppBar()
com o atalho "Ctrl + Alt + L". Em seguida, incluiremos a propriedade body
, que é o conteúdo de Scaffold()
. Nele, passaremos o Column()
, também do módulo MaterialApp
, e usaremos a propriedade children
para colocarmos cada um dos widgets. A ideia agora é incluirmos uma imagem, algo que ainda não aprendemos a fazer.
O Flutter nos disponibiliza widgets prontos que serão responsáveis pelo carregamento de imagens. Dentre as possibilidades comuns, temos quatro opções/constantes que já são fornecidas, evitando o trabalho de implementação. Dentre elas, temos: Image.network()
, que carrega uma imagem online;Image.asset()
, que carrega uma imagem de dentro do projeto; além de Image.file()
e Image.memory()
, responsáveis por carregar arquivos a partir do dispositivo ou na memória.
As abordagens mais comuns são a partir de Image.network()
ou Image.asset()
, e testaremos seus funcionamentos em nosso trabalho. Começando pelo primeiro, é exigido o envio de um argumento src
(source), que é uma string representando o endereço da imagem online. Para testarmos, usaremos uma imagem gratuita do site http://pixabay.com, cujo endereço passaremos entre aspas simples.
class BytebankApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Dashboard'),
),
body: Column(
children: <Widget>[
Image.network(
'https://cdn.pixabay.com/photo/2019/10/15/06/03/pinwheel-4550711_960_720.jpg')
],
),
),
);
}
}
Ao executarmos o Hot reload, a imagem será carregada na aplicação.
Porém, a equipe do Bytebank já nos enviou uma imagem própria para o aplicativo. Sendo assim, faz sentido aprendermos a abordagem com Image.asset()
, que não necessita de um endereço online. Portanto, substituiremos a chamada no código.
body: Column(
children: <Widget>[
Image.asset()
],
),
Em seguida, precisaremos fazer uma configuração para que o Flutter encontre a imagem desejada. Em projetos Flutter, existe um arquivo, chamado pubspec.yaml
, que é responsável por fazer toda a configuração do projeto, seja a configuração feita inicialmente, definição de dependências e assim por diante.
Acessaremos o pubspec.yaml
na raiz do projeto e encontraremos diversas informações, como o nome do projeto, a descrição que foi atribuída, versão do Flutter, versão do SDK, entre outras. No caso da adição de assets
, há uma parte com a instrução flutter
na qual encontraremos alguns comentários, incluindo instruções sobre como ativar os assets
. Isso na verdade é bem simples: basta "descomentarmos" o trecho referente a eles no código.
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
# To add assets to your application, add an assets section, like this:
assets:
- images/a_dot_burr.jpeg
- images/a_dot_ham.jpeg
Recomendamos manter a indentação das configurações iniciais, da mesma forma como está o padrão de uses-material-design
, pois a configuração desse arquivo é um pouco exigente e pode trazer problemas caso não seja seguida à risca.
Feita essa modificação, como o próprio IntelliJ é integrado com este arquivo, receberemos a sugestão de atualizá-lo. Clicando em "Packages get" ou "Packages upgrade" na barra de "Flutter commands" conseguiremos realizar a atualização. Ao final do processo, caso não ocorra nenhum erro, o IntelliJ exibirá um alerta de que os assets
que estamos passando não existem, pois ainda não configuramos nenhum tipo de asset no projeto.
O próximo passo será criarmos o caminho apresentado para disponibilização dos assets
. Na raiz do projeto, criaremos um novo diretório, chamado "images", com o atalho "Alt + Insert" e a opção "Directory". Em seguida, será necessário baixar o arquivo zipado com a imagem, disponibilizado nos exercícios do curso.
Extrairemos o arquivo bytebank_logo.png
e, pelo próprio IntelliJ, o moveremos para o diretório "images" do projeto. Se você estiver usando o Git, é possível que seja exibida uma mensagem perguntando se você deseja adicionar o arquivo ao seu repositório, algo que é opcional.
Com a imagem incluída no projeto, passaremos o seu nome no caminho indicado. Para facilitar, você pode clicar sobre o arquivo no menu lateral e usar o atalho "Shift + F6" para, na janela "Rename", selecionar o seu nome e a extensão. Não devemos nos esquecer de apagar os valores padrão que não fazem sentido para o nosso projeto.
assets:
- bytebank_logo.png
Clicaremos novamente em "Packages get" para atualizar o projeto, e a mensagem de alerta deixará de ser exibida. De volta ao main.dart
, recebemos outro apontamento dizendo que o Pubspec
foi editado. Se clicarmos em "Get dependencies", as dependências do projeto serão atualizadas, algo que poderá evitar problemas futuros. Agora, nos falta inserir o endereço completo da imagem em Image.asset()
.
class BytebankApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Dashboard'),
),
body: Column(
children: <Widget>[
Image.asset('images/bytebank_logo.png')
],
),
),
);
}
}
Ao fazermos o Hot reload, o emulador passará a exibir o logotipo do Bytebank.
O próximo passo será colocarmos o botão "Contacts" que deverá figurar no canto inferior esquerdo do aplicativo. Para isso, usaremos o widget Container()
, muito comum quando queremos incluir "caixas" na tela.
body: Column(
children: <Widget>[
Image.asset('images/bytebank_logo.png'),
Container(),
],
),
Dentro do Container()
, teremos outros dois widgets representando, respectivamente, um ícone e um texto. Sendo assim, incluiremos a propriedade child
recebendo um Column()
e, dentro desse widget, outra propriedade children
recebendo, por sua vez, o widget Icon()
. Por meio do objeto Icons
conseguiremos acessar os ícones do Material design, dentre eles o people
, que representa "pessoas".
body: Column(
children: <Widget>[
Image.asset('images/bytebank_logo.png'),
Container(
child: Column(
children: <Widget>[
Icon(Icons.people),
],
),
),
],
),
Executando a aplicação, o ícone será apresentado na tela do aplicativo.
Perceba que o Container()
não é apresentado, pois está em branco. Para que ele seja exibido, modificaremos o seu plano de fundo com a propriedade color
e a constante Colors.green
.
Container(
color: Colors.green,
child: Column(
children: <Widget>[
Icon(Icons.people),
],
),
),
Com isso, o ícone ganhará um plano de fundo verde.
O Container()
sempre crescerá com base em seu conteúdo interno. Logo, se temos apenas um ícone, seu tamanho será razoavelmente pequeno. Já se adicionarmos um widget Text()
com o texto "Contacts" na sequência, sua área crescerá um pouco mais.
child: Column(
children: <Widget>[
Icon(Icons.people),
Text('Contacts'),
],
),
Além disso, o Container()
também nos permite definir a sua altura e largura por meio das propriedades específicas height
e width
. Vamos testar:
Container(
height: 120,
width: 100,
color: Colors.green,
child: Column(
children: <Widget>[
Icon(Icons.people),
Text('Contacts'),
],
),
),
Interessante, não? Já aprendemos a colocar assets
, começamos a construir a estrutura inicial de nosso layout e, a seguir, faremos todas as modificações necessárias para atendermos às proporções de nossa proposta de implementação.
O curso Persistência com Flutter: crie um app com armazenamento interno possui 167 minutos de vídeos, em um total de 48 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.