Hive + Getx — Uma combinação poderosa — PARTE 1

Hive + Getx — Uma combinação poderosa — PARTE 1

Fala pessoal!

Há algum tempo eu tenho a vontade de escrever um artigo totalmente em português das 2 coisas que eu mais uso atualmente. o Hive que eu já utilizo desde o meu primeiro projeto para utilizar um banco de dados interno Nosql para coisas simples e o Getx que atualmente é o meu gerenciador de estado escolhido para os meus projetos atuais.

Nessa primeira parte do artigo para não ficar extenso, irei criar a estrutura dos packages para entrar o hive, porém iremos somente criar a tela de Todo com o Getx, para depois incluirmos o Hive, assim iremos ver como qualquer projeto, mesmo já iniciado pode ser beneficiado com o Hive.

Iremos basicamente criar um Todo utilizando o gerenciamento de estado do Getx e a persistência do Hive de um jeito simples para que qualquer nível conhecimento possa entender e utilizar da melhor forma possível também utilizando os conceitos de null-safety! Mas se você não conhece o Getx não se preocupe pois irei tentar passar o conceito de um jeito fácil os observáveis e etc. Portanto não desista e qualquer dúvida só me chamar

Como é comum, irei utilizar as nomenclaturas dentro do projeto em inglês, para que possam ser utilizadas por outras pessoas, pois irei disponibilizar o git, porém aqui toda a explicação será em português!

REPOSITÓRIO DO PROJETO

GitHub – brasizza/hive-medium-p1

CONFIGURANDO OS PACKAGES

Iremos utilizar aqui o menor número de packages possíveis para esse projeto, para que seja fácil a adaptação do seu projeto utilizando o Hive.

  • get: ^4.3.8 — O get para utilização da gerência de estado
  • hive: ^2.0.4 — o package do hive propriamente dita
  • hive_flutter: ^1.1.0 — package para ajudar na utilização do hive no flutter
  • hive_generator: ^1.1.1 — package para gerar nossos modelos e adapters mais facilmente (sem ele vc vai ficar maluco criando os models para o Hive)

SOBRE O GETX

Eu particularmente gosto e uso uma outra ferramenta quando estou utilizando o Getx , que chama, get_cli. ela poder ser comparada com o slidy, que te ajuda a criar controllers e etc com um único comando. Nesse projeto iremos usar ele também para que possam conhecer essa ferramenta que ajuda e muito o desenvolvimento

INICIANDO O PROJETO COM O GET_CLI

Se você está em um projeto novo e está com o get_cli configurado, vc pode digitar

get_cli init

escolher qual método que você vai utilizar (eu uso getx_pattern). Feito isso ele vai apagar sua pasta lib e recriar com o getMaterialApp e etc, portanto só faça esse comando se for um projeto novo!
Por questões de máquina, irei fazer o sistema todo utilizando o MacOs, porém como o flutter é extremamente adaptável, você não terá nenhum problema em rodar o mesmo app em outra plataforma.

Caso tenha executado o get init, seu projeto se parecerá com a seguinte estrutura

Não irei entrar em detalhes sobre a arquitetura, pois existe um tutorial completo na própria documentação do Getx >>aqui<<

CRIANDO O MODELO DE DADOS

Vamos começar criando nosso modelo de dados para o nosso TodoList antes mesmo de injetar o Hive, para que seja mais fácil a visualização de como inserir o Hive no projeto sem muitas modificações!

Dentro da pasta lib/app/data, iremos criar uma pasta para guardar nossa model. Como um projeto pode ter uma ou dezenas, por padrão centralizamos todos os modelos de dados dentro da uma pasta única e não dentro do módulo para sua reutilização ser mais fácil.

No caso desta model, teremos o id e o título como obrigatórios e descrição, tag e se foi finalizada ou não como possíveis nulos, porém o finalizado já começa como false. Iremos utilizar a tag para fazer um filtro mais pra frente no app só com as tags específicas.

CONSTRUINDO A TELA

Iremos construir uma tela simples na própria home, com um botão de adicionar que irá mostrar uma lista de itens digitados, ao clicar aparecerá um dialog para editar ou apagar o item selecionado.

Novamente, se você utilizou o get_cli , automaticamente ele irá criar um módulo home para você, já com as 3 pastas principais .

  • bindings — onde estão a injeção de dependência do módulo
  • controllers — onde estão as controllers do módulo. podem conter 1 ou várias dependendo da complexidade do seu módulo
  • views — onde estarão todas as telas do seu módulo, podendo também ter 1 ou várias de acordo com o quanto você irá quebrar sua tela.

CRIANDO A LISTA OBSERÁVEL NO GETX

Iremos criar de um jeito fácil e simples, assim como é a o Getx, uma lista de TaskModel observável para que nossa view possa saber que houve uma mudança de valores e possa ser atualizada. para isso iremos utilizar um rx_type do Getx chamado obs. Ao colocar .obs em propriedades da sua controller, você indica que aquela propriedade será observada e seu estado será transportado para as views que estejam escutando.

para iniciar o nosso projeto isso ja é o suficiente. Iremos alterando ao decorrer do artigo.

CRIANDO A VIEW

Assim como a controller, o get_cli também cria uma view padrão já com um Scaffold simples pronto para uso. Para uma melhor implementação, eu não irei dividir minha view em componentes, vou colocar tudo em uma view só, mas no mundo real isso fica impossível além de um código gigante, mas para o nosso exemplo está tudo ok!

Vamos criar um ListView e um floatingActionButton.

Como queremos a lista seja recuperada lá do nosso controller onde tem um list de TaskModel, precisamos criar um listview com o itemcount, itembuilder e etc. Nesse caso iremos criar um ListView.separated, para que a gente possa colocar um divisor entre cada linha, assim como fazemos normalmente em um listview sem muito segredo

A tela irá se parecer +_ com isso inicialmente.

Para testar nossa view, iremos criar um método na controller só para criar linhas aleatórias para teste. Portanto lá na nossa controller podemos criar um método chamado fakeTodo() onde só ira criar um modelo simples com titulo , descrição e uma tag aleatória, ficando assim

e no onPressed do ElevatedButton colocaremos o método controller.fakeTodo().

Se você estiver fazendo junto comigo irá perceber que você clicou umas 3 , 4 vezes e nada aconteceu, e você provavelmente está gritando na frente do monitor achando que fez algo errado! Mas calma, se vc apertar o hot reload os dados vão aparecer. Isso porque o controller está com o método observável, mas em nenhum momento você indicou que a view precisa escutar a alteração desse valor. Assim como o mobx que tem o observer, o Getx tem o obx, onde você envolve uma ou mais widgets que contém algum controle observável para que seja feita a reatividade. Porém se você envolver em algum widget que não tenha nenhuma propriedade observável, tanto no console, quanto no seu app (tela vermelha) irá aparecer a seguinte mensagem

[Get] the improper use of a GetX has been detected. You should only use GetX or Obx for the specific widget that will be updated. If you are seeing this error, you probably did not insert any observable variables into GetX/Obx or insert them outside the scope that GetX considers suitable for an update (example: GetX => HeavyWidget => variableObservable). If you need to update a parent widget and a child widget, wrap each one in an Obx/GetX.

portanto iremos envolver somente nossa listview no obx para que seja feita somente na parte necessária do seu código

Feito isso, a todo o clique do botão + nessa parte do código irá gerar o mesmo Todo, porém com isso ficará fácil de entender o conceito de obx + propriedade .obs

CRIANDO O DIALOG PARA CRIAR O NOSSA LINHA

O Getx tem a facilidade de não ter contexto, isso faz com que possamos fazer algumas coisas (certas ou erradas) no nosso projeto.

Para deixar tudo centralizado, iremos chamar o nosso dialog diretamente da nossa view, pelo menos nesse projeto, e para isso iremos criar uma pasta ‘components’ na view para separar o que é view e o que é componente, pois iremos criar nessa pasta a nossa página de dialog.

Para deixar a responsabilidade do dialog somente para o dialog, iremos criar uma controller separada para widget de dialog, assim podemos fazer a mudança de estado do checkbox sem colocar absolutamente nada na nossa homeController inicialmente.

No nosso dialog, iremos criar todos os TextEditingController e a nossa GlobalKey, deixando o processamento na controller, mas as partes visuais na view.

Como nosso title está como obrigatório, iremos fazer uma validação somente nesse campo, para que não seja submetido o formulário com o valor vazio.
Após isso iremos criar um método para salvar nosso Todo, criando um método no controller para inserir um TaskModel entro da nossa home_controller, na propriedade todoList que está observável e está sendo observada pela home_view, portanto ao alterar em qualquer tela, será acionado esse evento e a lista será repopulada com os dados inseridos.

Feito isso nossa controller terá um novo método ficando assim,

Teremos que fazer uma pequena alteração no nosso projeto que é, injetar o controller do Dialog no momento em que o botão de adicionar é acionado. então lá no nosso ElevatedButton do home_view iremos alterar para abrir o DialogTodo que criamos e antes de abrir injetar o controller para que a classe possa utilizar.

Para finalizar, iremos criar um checkbox na lista, para que o estado de feito/não feito seja alterado diretamente na tela. Na nossa home_view iremos criar um checkbox com o value sendo o done de cada linha do TaskModel (_todo.done) e criaremos um método no homeController para alterar o estado da linha.

E o controller da home

Note que no changeStatus precisamos dar um refresh na nossa lista, pois como estamos alterando somente 1 propriedade de um objeto dentro de uma lista o getx não sabe o que foi alterado, então forçamos a notificação para a view.
Com isso nosso projeto da primeira parte se encerra. Criamos um todoList que não tem nenhum tipo de persistência de dados (se você fechar o app e abrir novamente, tudo que você fez irá sumir).

Está curioso de como iremos inserir o Hive nesse projeto?

Não perca a parte 2 desse artigo aqui!