Utilizando o FullLifeCycleController no GETx

Fala galera!

Vamos para mais um artigo sobre Getx! Agora vamos ver como utilizar uma classe poderosa para pegar alguns eventos básicos (e outros não tão básicos) , como descobrir quando seu app vai para segundo plano ou entra em modo de inatividade.
O repositório estará no final do artigo para baixar, mas o importante é tentar fazer sem ele pois irei realmente explicar passo a passo!

INICIANDO O PROJETO

Para iniciar nosso projeto precisaremos criar nosso projeto e adicionar o getx nos nossos packages no pubspec.yaml

Até o momento do desenvolvimento deste artigo estamos utilizando a versão 4.6.1 do getx

Iremos criar um projeto simples de um timer que irá ficar rodando em um loop infinito que ao entrar em segundo plano ele irá parar e ao voltar ele vai continuar sem nenhuma interação, além de outros tipos de eventos que o getx nos proporciona que iremos abordar também!

Para iniciar o projeto com o Getx para utilização das rotas é necesário que nos alteremos o MaterialApp para GetMaterialApp assim o main vai saber que ele vai utilizar o Get como gerenciador das suas rotas!

Eu particularmente gosto bastante dessa estrutura de pastas

na nossa pasta lib, temos uma pasta app dentro dela uma pasta modules, onde irão todos os nossos módulos, e uma pasta routes onde irão todas as nossas rotas.

Inicialmente iremos criar um modulo simples chamado home, onde dentro dela irá ter um controller, uma page e um binding.
Eu particularmente gosto de usar a extension do vscode do grande Rodrigo Rahman que se chama Flutter & Dart Utilities, com ela você consegue criar uma estrutura de pasta com um clique , além disso eu também utilizo a extensão do próprio getx, que facilita a criação dos arquivos, pois vc digita ‘getpage’ e ele ja cria pra você uma estrutura simples de arquivo que agiliza e muito o processo de desenvolvimento

Clique em Getx: New feature digite o nome de uma pasta e ele já cria automaticamente a mesma estrutura (page/controller/binding)

Com o nosso primeiro módulo criado, vamos criar uma classe de rotas para que o nosso app saiba para onde vai e quais as rotas disponíveis. (Eu particularmente gosto de colocar todas as rotas no mesmo arquivo de rotas, mas fique a vontade para separar em seus projetos)

Vamos chamar nosso arquivo dentro da pasta routes de app_route.dart, e vamos criar nossa primeira rota como ‘/’ para indicar que esse será nossa primeira roda da nossa aplicação.

Vamos criar uma rota inicial com a nossa HomePage e colocar a nossa HomeBindings como os bindings que ele irá ler ao entrar nessa página

então quando nosso sistema iniciar ele vai pegar a rota ‘/’ e irá começar nosso app daí pra frente.

Porém ainda não colocamos as nossas rotas la no main.dart no GetMaterialApp, então, dentro do nosso GetMaterialApp, iremos colocar uma propriedade a mais chamada de getpages que espera basicamente uma lista de GetPages, então iremos colocar o AppPages.pages nessa propriedade para ele pegar e inserir todas as nossas rotas disponíveis no sistema ficando assim:

A partir desse momento você já vai estar utilizando Getx na sua aplicação utilizando o sistema de rodas to próprio Getx!

Se tudo deu certo seu sistema irá abrir na nossa HomePage!

ENFIM: O QUE É ESSE FULLLIFECYCLE ?

A Classe FullLifeCycleController veio para facilitar o desenvolvimento de algumas ações que podem ser capturadas, como por exemplo, se seu aplicativo foi para segundo plano, se mudou de darkmode pra light mode, rotação do device entre outros. Essa classe basicamente inclue a WidgetsBindingObserver , que é uma classe nativa do flutter de um jeito extremamente simples e didático do uso desses métodos sem grandes preocupações. Iremos abordar aqui os mais básicos , como mostrar ações quando o app for para segundo plano, pausar a execução do que estava fazendo e ao voltar, continuar.

ALTERANDO A MINHA HOME_CONTROLLER

Caso você não esteja familiarizado com o Getx, qualquer controller extende um GetxController para que assim possa utilizar todo o esquema de reatividade e todos os outros processos que o getx venha a utilizar, porem para usar esses processos de verificar os tipos de estados da nossa aplicação precisaremos trocar o nosso GetxController por FullLifeCycleController e colocar um mixin chamado FullLifeCycleMixin, ficando basicamente assim a nossa controller simples

Assim que inserirmos essa classe e esse mixin, seu sistema já ira dizer que você precisa implementar alguns métodos obrigatórios na sua classe que são justamente as que a gente precisa para o nosso artigo

onDetached — Acionado quando seu app é fechado (Não são todos os devices que chamam esse pois o processo de fechamento do app pode ser muito rápido e o flutter n consiga receber isso)

onInactive — Acionado quando o seu app estiver pausado mas sem receber nenhuma interação do usuário

onPaused — Acionado assim que o seu app vai para segundo plano

onResumed — Acionado assim que seu app retorna do segundo plano

Vamos fazer uma criação de um controller simples colocando somente um print em cada uma dessas ações para podermos observar o que cada estado faz.

Ao executarmos nossa aplicação em um celular,

quando colocamos a nossa aplicação em segundo plano ela executa
I/flutter (16129): onInactive
I/flutter (16129): onPaused

e assim que a nossa aplicação retorna para o primeiro plano ele executa o

I/flutter (16129): onResumed

Porém no android quando você clica no botão de voltar para encerrar o app ele executa o onDetached( e esse foi o único jeito que eu consegui que esse evento fosse acionado, pois matando o app pelo swipe o mesmo não é executado

I/flutter (16453): onInactive
I/flutter (16453): onPaused
I/flutter (16453): onDetached

Agora que vimos que os processos estão funcionando, vamos para o nosso projeto inicial:

Criar um contador que quando pausado, sua contagem pare, e ao retornar continue a contagem, porém que conte quantas vezes o usuário pausou a contagem saindo do app

ALTERANDO NOSSA CONTROLLER

Precisaremos criar uma propriedade observável no nosso controller para ir contabilizando o timer que ao iniciar nossa page ira incrementar 1 a cada 1 segundo que será mostrado na nossa view inicialmente. Iremos usar o Timer.periodic para ir incrementando nosso timer e jogar o valor para view ainda sem nenhum controle de sair ou voltar para a aplicação

e na nossa view

Se você executar seu projeto agora e colocar o seu app em segundo plano, contar até 10 e voltar você irá notar que o timer não parou, e que a contagem continuou integralmente.

PARANDO O TIMER!

Agora vamos parar o timer quando o aplicativo for para segundo plano.

Para isso vamos no nosso timer criar uma condição para saber se o timer deve continuar ou não sendo executado, e para isso vamos criar um uma propriedade chamada timerAtivo, que caso seja false o timer irá se encerrar, e obviamente esta propriedade começara em true

Feito isso dentro do nosso timer vamos checar se essa condição chegou em false para parar o timer. Porém só isso não vai fazer com que nosso timer pare, precisamos colocar a mudança dessa propriedade no onPaused, para que o nosso timer seja pausado no momento que entrar em segundo plano

Porém existe um comportamento estranho, ao voltar para a tela, nosso timer continua inativo, e para isso precisamos colocar no onResumed a instrução para que o nosso timer volte a funcionar, então, no onResumed, vamos colocar nossa propriedade de timerAtivo para true, (vamos colocar um snackbar , so para visualmente identificar que o timer esta voltado a ser executado), e chamamos novamente o método de percorrer o timer, o startTimer. Feito isso, assim que voltar o app em primeiro plano surgirá um snackbar e o timer voltará exatamente de onde parou.

BRINCANDO COM A REATIVIDADE DO GETX

Já que estamos utilizando o getx, que tal a gente também mostrar na tela quantas vezes o app foi para o segundo plano e voltou? com isso também utilizaremos mais uma propriedade em reatividade do getx.

Vamos criar uma propriedade observável chamada segundoPlano que começará em 0 e a cada ida ao onPaused a gente vai incrementar essa propriedade em +1

E na view colocamos mais um campo obx escutando essa propriedade

É isso pessoal. Com esse tipo de funcionalidade você pode fazer milhares de coisas , como por exemplo checar sua api para novas atualizações assim que o app voltar em primeiro plano, verificar expiração de login dentre outras coisas.

Segue o link para o repositório e qualquer dúvida estou aqui!

GitHub – brasizza/FullLifeCycle