Iniciando um aplicativo com Flutter parte 4

Tecnologia

Faaala devs e devas! Como vimos anteriormente na parte 3 modificamos nossa Todo list e incrementamos para ser possível adicionar novos todo’s. Agora iremos criar a opção de remover com um estilo bem daora! Bora lá!  Primeiramente precisamos verificar como se encontra nosso método que renderiza cada item da lista, pois é ele que iremos incrementar algumas coisas:

Acredito que a função de vocês esteja parecida com essa acima, onde ela recebe o contexto e o índice do item que deve ser renderizado. Bom, existem várias formas de remover um item, vai da sua imaginação e possibilidade de criar o que você quer criar. A forma que veremos aqui é principalmente para mostrar o que se pode fazer com Flutter de uma forma mais simples, que ele mesmo fornece para gente. Então chega de falação e bora lá!

ADICIONANDO DISMISSIBLE

Como podemos ver acima, foi adicionado um widget Dismissible como pai do CheckboxListTile, e vamos entender agora o que esse widget e suas propriedades fazem!

  O widget Dismissible torna algo “dispensável”,  e na prática, ao deslizar um item por exemplo, seja da esquerda para a direita ou o contrário, esse widget remove o item da tela conforme o deslizamento acaba. Visualmente será mais fácil de entender.

  As propriedades usadas consistem em:

  • key: uma chave única que precisa ser fornecida para que a remoção seja feita corretamente.
  • onDismissed: um método que recebe a direção do deslizamento e é possível realizar diferentes funções dependendo da direção.

  Não se preocupem com o método _onDismissed pois iremos implementar agora! É este método que irá receber a direção e o índice do item a ser removido.

Um método bem simples onde utilizamos um método de Listas que remove um item da lista dado o índice. E pronto! Podemos rodar no emulador/celular e verificar o resultado final!

Como podem ver, é criado um efeito bem legal! Claro que podemos melhorar e deixar indicado o que será feito ao deslizar. Bora lá!!

Como podemos ver no código acima, foi adicionada uma nova propriedade ao nosso widget Dismissible, que é a background. O funcionamento dela é simples, ela recebe um widget e o coloca como fundo ao deslizar. Então podemos informar o que vai acontecer ao deslizar de forma visual ao usuário. Na nossa lista, optei por mostrar uma linha onde à esquerda terá um ícone que representa “excluir” e logo ao lado escrito “excluir”. Bora rodar tudo isso e ver na prática!

E este é o efeito final que temos! Bem daora né? O mais legal é que você pode colocar o que bem entender (desde que caiba na linha do item). 

  DicaEz: A SizedBox pode ser usada para dar um espacinho entre widgets de forma bem simples e fácil como pode ser observado no widget que cria a linha de “excluir”.  Bom, acho que ainda falta alguma coisa…, me incomoda o fato de que, ao deslizar da direita para a esquerda o usuário não consegue enxergar o que vai ser realizado ao deslizar.. então bora melhorar isso!

Como podemos ver acima foi separado todo o Widget que montava o background e ainda foi adicionada uma nova propriedade do Dismissible, a secondaryBackground, que nada mais é do que o fundo que deve ser mostrado quando deslizado da direita para a esquerda.  Nosso método _dismissBackground ficou assim:

Ele recebe como parâmetros dois widgets, que serão colocados em linha, o primeiro seguido pelo segundo, e uma variável booleana que permite controlar o lado que os widgets aparecerão. Vamos ver na prática como vai ficar!

E com isso finalizamos a exclusão! Bom, agora para tornar a nossa todo list mais utilizável iremos adicionar uma forma de persistir os dados, para que ao fechar o aplicativo e abrir novamente, retorne os nossos afazeres da mesma forma que estavam. Então bora lá!

PERSISTINDO DADOS

Existem várias bibliotecas que auxiliam na persistência de dados em Flutter como hive, sqlite, sharedPreferences, entre outras. Iremos abordar e utilizar a sharedPreferences por questão de gosto, mas a forma que iremos implementar isso tornará possível trocar de biblioteca se necessário. Bora lá?

ADICIONANDO BIBLIOTECA

Para adicionarmos qualquer biblioteca no Flutter precisamos primeiro saber como ela funciona e como se instala, e para isso existe o site https://pub.dev que é similar ao npm de frameworks Javascript como React Native. Ao entrar no site, basta pesquisar por shared preferences que encontraremos a biblioteca, e na aba de instalação estará explicado como fazer para instalar a mesma.

IMPLEMENTANDO SERVIÇO DE PERSISTÊNCIA DE DADOS

Depois de instalado a biblioteca iremos agora implementar de fato para que possamos salvar qualquer mudança da nossa todo list no armazenamento local. Primeiro vamos criar um serviço para que assim seja possível alterar a biblioteca caso preciso.

Dentro da pasta lib do nosso projeto iremos criar duas outras pastas, uma que irá armazenar os serviços, portanto uma pasta chamada services, e outra que irá armazenar as interfaces dos serviços ou de outros métodos, portanto chamada de interfaces.

A vantagem e importância de criar uma interface é justamente para definir os métodos que deverão ser comuns aos nossos serviços, tornando mais simples a troca de biblioteca se preciso for.

Dentro de cada pasta iremos criar os respectivos arquivos para lidar com o shared preferences, então dentro da pasta services criaremos um arquivo persist_data_service.dart, e dentro da pasta interfaces criaremos um arquivo persist_data_interface.dart, e agora veremos como ficou:

Depois de criado esses arquivos, vamos primeiro implementar a interface, que deve conter os métodos comuns para persistir os dados. Bora lá!

Acima foi criado nossa interface com os métodos comuns que serão utilizados, simples assim! E agora para utilizarmos de fato ela, precisamos implementar no nosso serviço.

Como podemos ver acima, para implementar a interface basta utilizar o comando implements em nossa classe de serviço e completar os métodos que a interface fornece, que são o get, put e delete.

Como o shared preferences não lida automaticamente com os tipos de arquivo, ao atualizar alguma chave precisamos verificar qual tipo de arquivo é e então atualizar.  Pronto! Agora só precisamos instanciar o nosso serviço e implementar nos lugares que desejamos persistir os dados! Simbora!

Para instanciar nosso serviço basta importarmos tanto o serviço quanto a interface e declarar uma variável que irá receber essa instância. No caso o tipo da nossa variável deve ser a interface do nosso serviço, para que assim os métodos fiquem limitados aos que existem na nossa interface.  Nossa variável data agora não precisa de nenhum dado já definido pois iremos pegar do nosso storage se existir. Bora ver então!

Dentro na nossa classe _HomePageState, por ser uma classe stateful, existe o método initState, que podemos utilizar para realizar ações ao iniciar o estado da nossa aplicação, e nesse caso iremos buscar os nossos todos, e caso exista (!= null) vamos colocar no nosso estado local com setState.

Como os todos compõem uma lista, foi optado por salvar essa lista como json (encode) e depois, ao buscar os dados, realizar um parse (decode), ambos métodos existentes na biblioteca convert, que pode ser importada do core do dart desta forma: import ‘dart:convert’ as convert;. Por isso no método acima é feito um convert.jsonDecode(todos), para poder converter os todos que estavam como json para lista novamente, e depois de feito isso eles são salvos no estado local.

Assim, ao abrir nossa aplicação, se existirem todos salvos no armazenamento local, eles serão buscados e colocados na nossa lista.   Precisamos agora lidar com os métodos de adicionar e remover todo e o método que altera o estado do todo (concluído ou não), para que ao chamar algum desses métodos, atualize também os todos que estão sendo salvos no nosso localStorage.

Simplesmente chamamos o método que atualiza uma determinada chave no localStorage (put) logo após atualizar a modificação no estado local, e assim as modificações também serão salvas no localStorage, e como comentado anteriormente, ao salvar a lista de todos precisamos antes converter para json com o método jsonEncode da biblioteca convert.

E assim nossa Amazing Todo List está com os dados totalmente persistidos e funcionando de forma prática! No momento chegamos ao fim, mas continuem ligados que ainda há muita novidade vindo por aí! E se tiverem sugestões do que querem ver, só comentar! O código fonte se encontra em: https://github.com/RickMartian/amazing_todo_list. Nos vemos numa próxima!