Couchbase: o que é e como usá-lo no Flutter para criar um app offline first
13 min13 minutos de leitura
13 min13 minutos de leitura
Autor(a)
Mikael Diniz
Atualmente estou cursando Ciência da Computação na UFMA, sou apaixonado por programação, games, matemática, basquete, programação competitiva e LeetCode.
Inscreva-se em nossa Newsletter
Fique por dentro de conteúdos, insights e oportunidades do universo tech. Receba novidades e lançamentos direto no seu e-mail.
Você já criou alguma aplicação offline first que faz persistência de dados localmente? E uma que se comunica com APIs externas?
Cada uma dessas tarefas já é um desafio por si só; agora imagine a complexidade ao lidar com ambas ao mesmo tempo.
Neste artigo, vamos explorar como gerenciar dados tanto localmente quanto remotamente em uma aplicação e mostrar como o Couchbase simplifica esse processo.
Conhecendo o app Mood
Para entender o gerenciamento de dados locais e remotos, vamos trabalhar com um aplicativo Flutter de humor, em que a pessoa usuária pode escrever como está se sentindo.
Começaremos analisando a classe MyMood, que representa o humor:
O código cria um app Flutter com uma tela em que você registra o seu humor. Ao clicar no botão, o humor digitado é exibido na tela.
No entanto, isso acontece enquanto o aplicativo está aberto. Ou seja, se fechamos, todo o progresso é perdido e o humor da pessoa usuária não é registrado.
Nosso objetivo é fazer com que o app armazene o humor digitado pela pessoa usuária, para que o progresso se mantenha mesmo se ela fechar, desinstalar ou usar o aplicativo em outro dispositivo.
Qual o problema de usar apenas dados remotos em aplicativos Flutter?
Talvez, ao pensar na solução do problema dos dados que somem, tenha vindo à sua mente a ideia de usar um servidor remoto para armazenar o humor da pessoa usuária e recuperá-lo sempre que necessário. Algo como:
dynamic getMood(url) async {
dynamic mood = // faz requisição GET na URL
return mood;
}
E, de fato, essa solução não estaria de todo equivocada, mas traz alguns problemas. Primeiro, vamos analisar a imagem a seguir:
A abordagem de armazenar os dados exclusivamente no servidor nos deixa totalmente dependentes da resposta dele (como ilustrado pela imagem). E tem mais.
O grande problema é que a comunicação entre o cliente e o servidor pode falhar por diversos motivos, o que inutiliza o aplicativo.
Outro contra é que, ao abrir o app, o sistema acessa o servidor para buscar os dados, embora esses dados sejam os mesmos de um acesso anterior.
Por último, ao depender de dados remotos, as consultas constantes ao servidor podem sobrecarregar a infraestrutura, o que aumenta custos e impacta negativamente a performance do app.
Com essas limitações em mente, é hora de conhecermos um novo conceito: a persistência de dados.
O que é persistência de dados no Flutter?
A persistência de dados no Flutter é uma técnica de desenvolvimento em que salvamos os dados do aplicativo localmente.
É como se, dentro do dispositivo móvel, houvesse uma caixa onde guardamos os dados.
Esses dados podem ser itens de uma lista, informações de login, configurações e preferências da pessoa usuária (dark mode, por exemplo).
Ao armazenar dados diretamente no dispositivo, você elimina as requisições constantes ao servidor, reduzindo a dependência da conexão de internet e permitindo que o app continue funcionando sem rede.
E as consultas locais são muito mais rápidas que aquelas feitas a servidores remotos. Isso melhora a performance do app, principalmente em regiões com conexões lentas ou instáveis, onde a latência pode ser um fator limitante.
Outra vantagem é que o armazenamento local reduz a carga no servidor, pois muitas consultas, antes remotas, são processadas diretamente no dispositivo.
Entendendo nosso problema, chegou o momento de criar nosso banco local e, para fazê-lo, usaremos o Couchbase.
Para começar, adicione as seguintes dependências no arquivo pubspec.yaml:
dependencies:cbl_flutter:cbl_flutter_ce:cbl:## Lembrando que você deve utilizar as versões mais recentes
Depois, execute:
flutter pub get
Com as dependências instaladas, vamos começar configurando o banco de dados local:
Em seguida, crie a classe que será responsável por armazenar os dados da nossa coleção do Couchbase:
Neste trecho de código, criamos a classe que será responsável pelo armazenamento local da nossa aplicação e criamos um método de inicialização.
Como salvar dados no banco local com persistência no Flutter?
Agora que a estrutura do banco está pronta, vamos criar a função add para salvar o humor no banco:
class DatabaseService {
AsyncDatabase? database;
//Outros métodos
Future<bool> addMood(MyMood mood) async {
final collection = await database?.createCollection(
CouchbaseContants.collection,
CouchbaseContants.scope,
);
if (collection != null) {
final document = MutableDocument(mood.toMap());
final resultSave = await collection.saveDocument(
document,
ConcurrencyControl.lastWriteWins,
);
return resultSave;
}
return false;
}
//Outros métodos
}
Essa função cria um MutableDocument com os dados do humor e o salva no banco de dados. O campo type é usado para identificar o tipo de documento, o que facilita consultas posteriores.
Consultando os dados armazenados no dispositivo
Agora, vamos buscar o humor salvo no banco com a função abaixo:
class DatabaseService {
AsyncDatabase? database;
//Outros métodos
Future<List<MyMood>?> fetch({
required String collectionName,
}) async {
await init();
await database?.createCollection(
collectionName,
CouchbaseContants.scope,
);
final query = await database?.createQuery(
'SELECT META().id, * FROM ${CouchbaseContants.scope}.$collectionName''}',
);
final result = await query?.execute();
final results = await result?.allResults();
final data = results
?.map((e) => {
'id': e.string('id'),
...(e.toPlainMap()[collectionName] as Map<String, dynamic>)
})
.toList();
final moodsFromData = data?.map((e) => MyMood.fromJson(e)).toList();
return moodsFromData ?? [];
}
//Outros métodos
}
Neste código, através do método fetch, fazemos a busca do humor armazenado e fazemos o retorno dele.
Pronto, usamos como base a mesma aplicação que havíamos criado anteriormente e adicionamos o armazenamento local dos dados.
Como sincronizar dados locais e remotos em apps Flutter?
Já entendemos os problemas de usar apenas dados remotos, vimos como o armazenamento local auxilia e até criamos um banco de dados local. Mas ainda falta algo, certo?
Se um aplicativo utiliza o Coucbase (armazenamento local), mas em outras funcionalidades utiliza o banco de dados na nuvem, é preciso programar o aplicativo de forma que os dois bancos se comuniquem, evitando erros nos dados.
Assim, vamos ver como conectar o banco local com o servidor.
Felizmente, o Couchbase facilita esse processo.
O que é Couchbase?
O Couchbase é uma plataforma de banco de dados que combina o melhor do NoSQL e SQL.
O Couchbase oferece uma infinidade de funcionalidades, e entre elas está a sincronização entre banco local e remoto, que iremos usar neste artigo. Para começar, vamos configurar a sincronização usando o Couchbase Capella e o Sync Gateway.
Vamos começar!
Como utilizar o Couchbase no Flutter?
Aqui vai um passo a passo de como usar o Couchbase no Flutter:
Com a conta e o cluster criados, siga para o próximo passo.
Passo 2: Bucket e Collection
Para armazenar nossos dados, precisamos criar um bucket e uma collection. O bucket é como uma grande caixa, e dentro dele estão as caixas menores, as collections, que são as responsáveis por armazenar, de fato, os dados. Siga os passos abaixo:
Acesse o data tools (ferramentas de dados);
Dentro do data tools, crie um bucket chamado moodbucket;
Dentro do moodbucket, crie o scopemoodscope;
No escopo, adicione a collectionmoodcollection.
Passo 3: Configuração de serviço de app e endpoint:
Vá para App Services e crie um serviço chamado moodservice;
Abra o serviço e adicione um endpoint e conecte à collection moodcollection;
Dentro do endpoint, acesse App Users (se necessário clique em “resume endpoint” para ativar o endpoint);
Configure um novo user e atribua o canal moodcollection.
Passo 4: Configurando o projeto
Agora, dentro do nosso projeto Flutter, modificaremos a nossa classe de constantes do Couchbase, e adicionaremos alguns atributos que irão nos auxiliar a fazer a sincronização com o servidor remoto:
class CouchbaseContants {
static String userName = 'teste'; //nome do seu user
static String password = 'teste'; //senha do user
static String publicConnectionUrl ='endpoint'; //seu endpoint
static const String channel = 'moodcollection';
static const String collection = 'moodcollection';
static const String scope = 'moodscope';
}
Com todos os atributos adicionados, modifique a classe do nosso banco de dados para adicionar as funções e atributos que serão responsáveis pela sincronização:
Além de adicionar o atributo replicator, criamos também a função startReplication, que é responsável por sincronizar os nossos dados. O método de carregar humor foi modificado e, agora, usa a nossa função de sincronizar dados.
Pronto, finalizamos o app! Agora é só abrir a aplicação e testar.
Offline first no Flutter e exemplos
Nossa aplicação foi desenvolvida para sincronizar o banco de dados local com o remoto. O mais interessante é que ela funciona sem conexão com a internet, graças ao armazenamento local.
Na prática, sem perceber, adotamos o conceito de Offline First. Você provavelmente já encontrou essa abordagem em aplicativos populares.
No WhatsApp, por exemplo, quando você envia uma mensagem e está offline, ela fica pendente e é enviada automaticamente assim que a conexão volta.
No Google Maps, você pode navegar por rotas salvas mesmo sem internet. E esses são só alguns exemplos, já que essa abordagem está presente em muitos outros aplicativos.
O que é offline first?
Offline First é quando um aplicativo Flutter continua funcionando sem conexão com a internet. Assim, a pessoa usuária tem uma experiência mais fluida e sem interrupções, mesmo quando estiver sem internet, e neste artigo, fizemos tudo isso na prática.
Conclusão
Você mergulhou no Offline First, utilizando o Couchbase.
Mas não paramos por aqui!
Se você quer aprender ainda mais sobre os princípios do Offline First, a Alura preparou uma lista de conteúdos especiais: