Alura > Cursos de Mobile > Cursos de Flutter > Conteúdos de Flutter > Primeiras aulas do curso Flutter: graphql e suporte offline

Flutter: graphql e suporte offline

Configuração e exibição de dados - Apresentação

Introdução ao Curso de Flutter

Olá! Gostaríamos de dar as boas-vindas a mais um curso de Flutter aqui na Alura.

Meu nome é William Bezerra, sou um homem pardo, de cabelo preto e barba preta, e serei o instrutor ao longo de toda esta jornada, na qual desenvolveremos o aplicativo Memorando.

Descrição do Aplicativo Memorando

Um aplicativo para gestão de tarefas domésticas utilizará o conceito e a aplicação do GraphQL para realizar diversas atividades e possibilitar a conexão entre um cliente GraphQL e um aplicativo Flutter. Com isso, conseguiremos criar atividades, listar atividades em uma listagem paginada com scroll infinito, semelhante ao que ocorre em aplicativos como Instagram e Twitter. Além disso, será possível interagir e alterar, por exemplo, marcando uma atividade como concluída.

Funcionalidades de Subscriptions no GraphQL

Teremos também a questão das subscriptions, um conceito interessante do GraphQL, que permite ouvir interações em tempo real. Por exemplo, se outro usuário ou nós mesmos marcarmos uma atividade como concluída, a quantidade de atividades pendentes será reduzida. Da mesma forma, se alguém adicionar uma nova atividade, a quantidade de atividades pendentes aumentará automaticamente em tempo real.

Pré-requisitos para o Curso

Para acompanhar este curso, é importante já ter conhecimento básico sobre o funcionamento de APIs e chamadas de dados, para absorver o máximo de conteúdo. Nos encontramos na próxima aula.

Implementação da Classe TaskViewModel

Agora, vamos começar a implementar algumas funcionalidades no nosso aplicativo. Vamos criar uma classe TaskViewModel que irá gerenciar o estado das tarefas e notificar a interface do usuário sobre as mudanças.

Primeiro, vamos definir a estrutura básica da classe TaskViewModel que estende ChangeNotifier. Isso nos permitirá usar o padrão de notificação para atualizar a interface do usuário quando o estado das tarefas mudar.

class TaskViewModel extends ChangeNotifier {
}

Métodos para Gerenciamento de Tarefas

Dentro dessa classe, vamos implementar o método toggleTaskStatus, que será responsável por alternar o status de uma tarefa entre concluída e não concluída. Inicialmente, vamos apenas definir a assinatura do método.

Future<void> toggleTaskStatus(Task task) async {
}

Em seguida, vamos adicionar o método updateTask, que será usado para atualizar uma tarefa existente. Este método chamará um caso de uso (use case) que lida com a lógica de atualização da tarefa e, em seguida, chamará o método refresh para notificar a interface do usuário sobre a mudança.

Future<void> updateTask(Task task) async {
  await _updateTaskUseCase(task: task);
  refresh();
}

O método _updateTaskUseCase é responsável por realizar a operação de atualização da tarefa. Vamos garantir que ele seja chamado corretamente dentro do método updateTask.

await _updateTaskUseCase(task: task);

Além disso, vamos implementar o método deleteTask, que será responsável por excluir uma tarefa com base no seu ID. Assim como no método de atualização, ele chamará um caso de uso específico para a exclusão e, em seguida, atualizará a interface do usuário.

Future<void> deleteTask(int id) async {
  await _deleteTaskUseCase(id);
  refresh();
}

O método _deleteTaskUseCase é chamado para realizar a exclusão da tarefa.

await _deleteTaskUseCase(id);

Conclusão sobre a Classe TaskViewModel

Com esses métodos, nossa classe TaskViewModel está preparada para gerenciar as operações básicas de uma tarefa, como alternar o status, atualizar e excluir. Isso nos permitirá manipular as tarefas de forma eficiente e manter a interface do usuário sempre atualizada com o estado mais recente das tarefas.

Configuração e exibição de dados - Conhecendo o Hasura e configurando o banco de dados

Criação do Aplicativo Memorando

Durante uma conversa com nosso parceiro, colega de quarto, cônjuge ou namorada, decidimos criar um aplicativo para gerenciar as tarefas diárias de nossa casa. Como desenvolvedores, vimos nisso uma oportunidade de ter controle sobre nossas tarefas e, ao mesmo tempo, adquirir experiência. Assim, nasceu o aplicativo chamado Memorando.

Funcionalidades do Aplicativo

Com o Memorando, podemos criar novas tarefas, como "tirar o lixo", adicionar descrições, definir categorias, salvar essas informações, marcar tarefas como concluídas, editar detalhes e até apagar atividades. No entanto, percebemos que o aplicativo funcionava apenas localmente, o que significava que, ao fechar e reiniciar, perderíamos todos os dados. Precisávamos de um back-end para salvar e controlar os dados remotamente, permitindo que outras pessoas também pudessem usar o aplicativo.

Escolha da Tecnologia para o Back-end

Após estudar as alternativas para criar um banco de dados e configurar o back-end, estabelecemos alguns pré-requisitos: o aplicativo deveria funcionar offline e manter os dados mesmo sem internet, além de ser leve para não sobrecarregar o dispositivo com mais de 20 mil tarefas. Optamos por usar GraphQL, que nos oferece controle dos dados e um cliente próprio para cache, além de ser uma solução de low-code.

Implementação com Hasura

Encontramos o Hasura, uma ferramenta que nos permite criar e modelar dados automaticamente, gerando um back-end GraphQL para nossa aplicação. Com o Hasura configurado, temos uma estrutura onde a aba de data centraliza todos os dados, permitindo criar e gerenciar tabelas, como a tabela de tasks.

Integração com GraphQL

Para integrar o back-end e acessar os dados, utilizamos o GraphQL. No Hasura, a aba de API nos dá acesso ao Playground, onde podemos estruturar e definir chamadas de GraphQL. Vamos começar criando uma query básica.

Estruturação das Queries GraphQL

Primeiro, definimos uma query vazia:

query {

}

Em seguida, especificamos que queremos acessar as tasks:

query {
  tasks
}

Para obter detalhes específicos, como o título das tarefas, expandimos a query:

query {
  tasks {
    title
  }
}

Podemos adicionar mais campos, como o ID das tarefas:

query {
  tasks {
    id
    title
  }
}

E, finalmente, incluímos o campo isCompleted para verificar se a tarefa foi concluída:

query {
  tasks {
    id
    title
    isCompleted
  }
}

Próximos Passos: Integração com Flutter

Ao executar essas queries no Playground, recebemos um JSON com os dados solicitados. Essa é a essência do GraphQL: permitir que busquemos exatamente os dados de que precisamos. Na próxima etapa, veremos como integrar essa estrutura no Flutter, permitindo que nosso aplicativo Memorando se conecte ao back-end e funcione de forma completa e eficiente.

Configuração e exibição de dados - Configurando o GraphQL no Flutter

Introdução ao Uso do GraphQL com Flutter

Agora que já entendemos como o GraphQL funciona com o Razor e conseguimos fazer toda a configuração do nosso back-end, precisamos configurar o Flutter para utilizar a ferramenta. Como faremos isso? Vamos começar utilizando um package específico para essa estrutura, chamado GraphQL Flutter.

Adicionando o Package GraphQL Flutter

Para adicionar o package, abriremos o terminal do VSCode e executaremos o seguinte comando:

flutter pub add graphql_flutter

Com isso, o package será adicionado. Este é um dos mais utilizados pela comunidade para essa configuração. Caso queiramos utilizar outro package que vimos, como um criado pela comunidade para usar com o Razor, podemos ficar à vontade. A ideia é que funcione de maneira semelhante, mas o GraphQL Flutter possui uma estrutura mais robusta para trabalhar com cache e outras funcionalidades, e é ele que utilizaremos ao longo do curso.

Verificando a Configuração no pubspec.yaml

Após executar o comando, o package será adicionado. Vamos abrir o menu lateral do VSCode e acessar o arquivo pubspec.yaml para verificar se está tudo correto. Dentro das dependências, o GraphQL Flutter versão 5.2.0 Beta deve estar adicionado:

graphql_flutter: ^5.2.0-beta.8

Configuração do Cliente GraphQL

Com isso, iniciaremos a configuração da API. Vamos abrir a pasta "config" e criar um arquivo chamado api_client.dart. Nele, criaremos uma classe ApiClient, onde configuraremos uma função para criar nosso cliente GraphQL. A estrutura básica será a seguinte:

// Filename: api_client.dart

class ApiClient {
  static GraphQLClient create() {
    // Configurações serão adicionadas aqui
  }
}

Definindo o Cliente com Link e Cache

Dentro da função create, definiremos o cliente com final client = GraphQLClient(...), e faremos as configurações de link e cache. Após isso, retornaremos o cliente:

static GraphQLClient create() {
  final client = GraphQLClient(link: link, cache: cache);
  return client;
}

Configuração do Link HTTP

Para o link, criaremos uma variável link que será igual a HttpLink(...). Ele receberá como parâmetro uma URI, que é a string de acesso ao GraphQL. No caso do Razor, conseguiremos essa informação na aba do Razor, onde há um endpoint GraphQL. Copiaremos esse link e o colaremos no VSCode:

final httpLink = HttpLink('https://uncommon-maggot-51.hasura.app/v1/graphql');

Autenticação com AuthLink

Com isso, já temos o link configurado. Entretanto, se voltarmos ao Razor, ele possui uma chave de acesso, de autenticação, que é um token extenso necessário para garantir que o projeto tenha as credenciais necessárias para o acesso. Precisamos configurar essa chave dentro do link para que, ao conectar, ele passe o valor e possamos conectar diretamente.

Para isso, faremos a seguinte configuração no código, dentro do nosso client. Vamos criar outra variável, que será igual a um AuthLink:

final authLink = AuthLink(
  getToken: () => const String.fromEnvironment('HASURA_TOKEN'),
  headerKey: 'x-hasura-admin-secret',
);

Como essa informação é sigilosa, não podemos inseri-la diretamente no código. Para isso, utilizaremos o DART DEFINE, que é a configuração do DART para definir variáveis de ambiente dentro do projeto.

Concatenando Links e Configurando Cache

Com isso, temos os dois links, mas o authLink ainda não está sendo utilizado. Vamos criar outra variável para concatenar os dois links, completando a configuração:

final link = authLink.concat(httpLink);

Precisamos configurar nosso cache para armazenar e controlar dados, conforme mencionado anteriormente. Vamos criar outra variável chamada cache e inicializar o GraphQLCache:

final cache = GraphQLCache();

Próximos Passos

Com isso, temos nosso client configurado. Agora, precisamos utilizá-lo para realizar o primeiro acesso diretamente no Razor, baixar os dados, obtê-los via API e exibi-los na nossa listagem. É exatamente isso que faremos na próxima etapa.

Sobre o curso Flutter: graphql e suporte offline

O curso Flutter: graphql e suporte offline possui 153 minutos de vídeos, em um total de 49 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