Alura > Cursos de Mobile > Cursos de Flutter > Conteúdos de Flutter > Primeiras aulas do curso Flutter: otimizando o cache offline com Sembast

Flutter: otimizando o cache offline com Sembast

Configuração do Sembast - Apresentação

Boas-vindas a mais este curso da Alura. Sou Yago Oliveira e acompanharei você neste curso sobre o conceito de Offline First.

Audiodescrição: Yago se identifica como um homem branco. Possui cabelos curtos e castanhos escuros, penteados para o lado, uma barba média e um bigode da mesma cor. Usa uma camiseta preta e está sentado em uma cadeira preta. Ao fundo, uma parede lisa e clara iluminada em tons de azul, com um pôster dos vilões de Star Wars ao centro.

Conhecendo o projeto

Vamos trabalhar com o ClimApp, um aplicativo de previsão do tempo que atualmente funciona totalmente online. Nosso objetivo será transformá-lo em uma aplicação Offline First, utilizando a estratégia de cache com banco de dados sem baixa.

O que aprenderemos?

Neste curso, aprenderemos diversos conceitos utilizados no mercado, como:

O adapter serve para fazer a conexão com nosso banco de dados. Já os records são a estrutura de dados do Dart, para retornar mais de um tipo em uma determinada função.

Realizaremos consultas e criaremos services (serviços) para verificar se o dispositivo possui conectividade. Faremos isso de maneira adequada e exibiremos o estado de conectividade do dispositivo à pessoa usuária por meio de um banner.

Pré-requisitos

Para aproveitar bem este curso, é importante ter:

Esperamos encontrar você nos próximos vídeos!

Configuração do Sembast - Conhecendo o projeto e instalando o Sembast

Vamos acessar o editor de código, abrir o emulador e analisar nossa aplicação, o ClimApp, com a qual trabalharemos:

Tela inicial do aplicativo ClimApp. No topo, a logo em branco diz 'Climapp' com raios de sol estilizados no C. Abaixo, há uma ilustração de um globo com nuvens, sol e chuva, representando diferentes condições climáticas. Abaixo da imagem, o texto em branco diz 'Boas-vindas!'. Na parte inferior, há um botão azul claro com a palavra 'Entrar' acompanhada de uma seta à direita. O fundo da tela é um degradê de azul médio para escuro.

Ao clicar no botão "Entrar", este aplicativo exibe a previsão do tempo de quatro cidades: Sorriso, Barreiras, Rio Verde e Maracajú.

Tela de previsão do tempo por cidades do aplicativo ClimApp. No topo, há uma barra de pesquisa com 'Digite a cidade' e um ícone de lupa à direita. Abaixo, uma lista de cidades com ícones de condições climáticas e temperaturas: 'Sorriso' com ícone de nuvem e chuva leve, 22 graus; 'Barreiras' com ícone de sol, 33 graus; 'Rio Verde' com ícone de nuvem e chuva leve, 28 graus; 'Maracaju' com ícone de nuvem e chuva leve, 30 graus.

Ao clicar em Barreiras, por exemplo, podemos ver a previsão e a situação climática atual. Atualmente, está fazendo 33 graus em Barreira. Além disso, o aplicativo mostra a fase da lua e a temperatura dos próximos dias em Barreiras.

Tela de previsão do tempo para Barreiras, BA, no aplicativo ClimApp. No topo, há a data 'Hoje 06/02/2025'. Abaixo, um ícone de sol indica tempo limpo com a temperatura de '33°'. Há informações de 'Umidade: 36%' e 'Min/Max: 17/33°'. Na parte inferior, previsões para os dias seguintes: 'Qui (06/02)' com um ícone de fase da lua e temperaturas '33/17°', e 'Sex (07/02)' também com ícone lunar e '34/20°'.

Conhecendo o problema

Vamos imaginar que ficamos sem internet. Desligaremos o Wi-Fi do dispositivo e reiniciaremos a aplicação rapidamente para verificar o comportamento. A tela de boas-vindas aparece normalmente. No entanto, ao clicarmos em "Entrar", ocorre um erro, e a seguinte exceção aparece na tela:

Exception: Sem conexão com a internet

Isso revela um problema: nossa aplicação não funciona sem conexão à internet.

Vamos imaginar que somos pessoas com problemas de conectividade, no meio do trânsito, passando por um túnel, ou em uma viagem longa entre cidades, sem conexão à internet, mas desejando saber a previsão do tempo para a cidade de destino.

Talvez sejamos pessoas que trabalham no setor agrícola, que saíram da sede da fazenda para um pivô ou outro sistema de irrigação, precisando decidir se irrigarão ou não a lavoura, mas estamos longe da sede e sem internet. Isso representa um grande transtorno.

Criando a solução com Sembast

Para resolver essa questão, precisamos que nosso aplicativo busque dados na API quando houver internet, mantendo os dados atualizados, e que armazene essas informações na memória interna. Assim, quando acessarmos novamente, ele poderá trazer os últimos dados obtidos.

Para implementar essa funcionalidade, utilizaremos um banco de dados chamado Sembast. O Sembast é um banco de dados totalmente desenvolvido em Dart, e é NoSQL, baseado em documentos. Cada documento armazenará as informações da cidade que estamos consultando.

A vantagem do Sembast é que ele proporciona uma excelente integração com Flutter, por ser 100% feito em Dart, além de ser muito simples de usar.

Para fazer o Sembast funcionar, precisaremos de duas bibliotecas adicionais:

O Path Provider mostra o local onde vamos armazenar os dados. Já Path gerencia os caminhos dos arquivos dentro da nossa aplicação. Vamos lidar com os arquivos internos do nosso aplicativo.

Entendendo o conceito de cache

Para entender como o cache funciona, vamos imaginar um restaurante muito movimentado. Os pratos populares são preparados com antecedência e mantidos aquecidos, prontos para serem servidos quando necessário. Em uma pizzaria, por exemplo, se a pizza de marguerita é a que sai mais rápido, a pessoa pizzaiola já trabalha para deixar essas pizzas pré-prontas.

Isso é semelhante ao funcionamento de um cache. Quando guardamos dados no cache, seja em um banco de dados ou outras ferramentas, podemos acessar rapidamente um dado ou lidar com a indisponibilidade do dado naquele momento, como no caso do nosso conceito de Offline First.

Instalando os pacotes necessários

Agora, vamos fazer a instalação dos packages e do Sembast. Como mencionado, vamos instalar três packages: Sembast, PathProvider e Path.

Acessando o VS Code, clicaremos no ícone de três pontos no canto superior esquerdo e selecionaremos "Terminal > New Terminal" ou "Novo Terminal", se estiver em português. Isso exibirá a aba do terminal na parte inferior central da tela, abaixo da área de edição de código.

Dentro do terminal, executaremos o seguinte comando:

flutter pub add sembast

Após pressionar "Enter", aguardaremos a instalação. Após a instalação, o VS Code fará o GET e, em seguida, instalaremos o PathProvider com o seguinte comando:

flutter pub add path_provider

Aguardaremos a execução, o VS Code atualizará os pacotes, e limparemos o terminal com o comando clear.

clear

Em seguida, executaremos o comando para instalar o último pacote necessário para usar o Sembast:

flutter pub add path

Após executar o comando, ele baixará as dependências, e teremos todos os pacotes instalados. Com isso, a dependência do Sembast já estará no nosso aplicativo.

Próximos passos

A seguir, implementaremos o Sembast no aplicativo e logo começaremos a codificar.

Configuração do Sembast - Implementando o Sembast com o adapter

Vamos começar a implementar o Sembast em nosso aplicativo. Antes de começar a codar, vamos refletir um pouco.

Antecipando desafios na escolha do banco de dados

Vamos imaginar que integramos o Sembast em cada uma das funcionalidades do aplicativo ClimaApp. Embora nosso aplicativo tenha poucas funcionalidades, imagine que estamos lidando com uma aplicação que possui 20, 30 ou 40 funcionalidades, e cada uma delas implementou o Sembast.

Se o Sembast for descontinuado, como acontece com muitos projetos mantidos pela comunidade, e não houver mais atualizações, ou se surgir outro banco de dados mais rápido, mais integrado e com funcionalidades melhores, teríamos um grande trabalho para migrar para esse novo banco. Precisaríamos alterar cada funcionalidade e cada arquivo, substituindo o Sembast pelo novo banco desejado.

Utilizando o padrão Adapter para flexibilidade

Para evitar esse trabalho árduo, utilizaremos um padrão de projeto chamado Adapter, que adaptará nosso pacote ou subsistema dentro do aplicativo.

Voltando ao VS Code, acessaremos a aba do explorador de arquivos. Na pasta do nosso projeto, acessaremos o caminho de pastas "lib > src > core" e criaremos uma nova pasta dentro de "core". Para isso, clicaremos com o botão direito sobre "core", selecionaremos "New Folder" (nova pasta) e a nomearemos como local_storage_adapter, que significa adaptador de armazenamento local.

Após pressionar "Enter" para criar a pasta, clicaremos com o botão direito sobre ela, selecionaremos "New File" (novo arquivo) e criaremos primeiro nosso contrato, que definirá como o Sembast, ou qualquer banco de dados, deve se comunicar.

Criando a classe abstrata para o adaptador

Precisamos definir como nosso banco de dados deve operar e qual contrato estabeleceremos para que ele funcione conforme esperado. O novo arquivo se chamará local_storage_adapter.dart.

No interior desse arquivo, criaremos uma classe abstrata, que não será implementada diretamente, mas sim definida pela pessoa desenvolvedora que trabalha no projeto. A classe será abstract class LocalStorageAdapter.

Entre suas chaves, teremos três métodos. O primeiro método, Future<void> start(), inicializará nosso banco de dados.

local_storage_adapter.dart:

abstract class LocalStorageAdapter {
    Future<void> start();
}

Note que não há implementação, pois é um contrato. A implementação será feita por outra classe. Esse é um conceito de orientação a objetos.

Se precisar relembrar alguns conceitos, recomendamos revisitar o curso de Orientação a Objetos em Dart, disponível na plataforma da Alura.

Definição dos métodos essenciais

Vamos passar para o próximo método abaixo do start(). Vamos digitar Future<>, que terá um retorno, pois o método que vamos colocar é o get(), onde obteremos nossos dados. Ele retornará o tipo Map<String, dynamic>, o Map com o qual já temos costume de trabalhar nos cursos de Dart e nos conteúdos da plataforma.

abstract class LocalStorageAdapter {
    Future<void> start();
    Future<Map<String, dynamic>> get();
}

Entre os parênteses do get(), será necessário passar o store. O Sembast é um banco de dados não relacional orientado a documentos, portanto, precisamos especificar qual documento ele deve retornar, ou seja, onde está o dado que precisa ser acessado.

Vamos usar um bloco de chaves, dentro do qual teremos o required para indicar que é necessário, especificar String para o tipo de dado que passaremos, e definir o store, que é o arquivo que ele deve retornar.

abstract class LocalStorageAdapter {
    Future<void> start();
    Future<Map<String, dynamic>> get({required String store});
}

Abaixo desse método, vamos adicionar o último. Como se trata de um cache, precisamos que ele não apenas salve o que é necessário, mas também atualize o dado existente. Não temos um banco relacional que armazena todas as informações, apenas queremos que ele atualize o dado já existente. Assim, teremos uma função que apaga o antigo e coloca o novo no lugar.

Vamos definir um Future<> do tipo void, que apagará e salvará. Após fechar o símbolo de maior que, colocamos eraseAndAdd() que significa "apagar e adicionar", ou seja, apagar o antigo e colocar o novo.

Entre os parênteses, adicionaremos um bloco de chaves, entre as quais especificaremos o documento que queremos acessar. Ele é required, do tipo String e se chama store.

Também indicaremos o dado que será salvo no lugar. Após o store, adicionaremos uma vírgula, um required e utilizaremos nosso Map<String, dynamic>. Nomeamos esse Map como data, pois é o dado que será salvo, colocamos vírgula, e finalizamos a linha com ponto e vírgula.

Após o ponto e vírgula, pressionaremos "Enter" para indentar o código automaticamente.

Future<void> eraseAndAdd({
    required String store,
    required Map<String, dynamic> data,
});

Finalizamos a codificação do projeto.

Relembrando o conceito de padrão de projeto

Ao longo do desenvolvimento do projeto, podemos nos perguntar o que é um padrão de projeto. Temos conteúdo sobre isso na plataforma, mas vamos relembrar.

Vamos imaginar uma ferramenta elétrica, como uma furadeira ou parafusadeira, e uma tomada. Nesse momento, nos deparamos com um plug de três pinos que não encaixa em nossa tomada.

Nesse caso, compramos um adaptador. O adaptador permite que a tomada, que não se encaixa no padrão, possa ser usada. Nosso adapter do banco de dados funciona da mesma forma: adicionaremos o Sembaste na implementação da classe abstrata, criaremos um adaptador, e o Sembaste se comunicará com nossa aplicação.

Caso precisemos trocar, basta ajustar o adaptador. Se o plug vier de outro padrão, trocamos o adaptador, sem precisar trocar a tomada.

Próximos passos

Já criamos nosso contrato e nossa classe abstrata. A seguir, vamos implementar a nossa classe.

Sobre o curso Flutter: otimizando o cache offline com Sembast

O curso Flutter: otimizando o cache offline com Sembast possui 122 minutos de vídeos, em um total de 52 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:

Aprenda Flutter acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas