Flutter: Navigator 2.0 + NotificationListener

Gabul
4 min readJan 13, 2021

Olá dev, hoje iremos falar de um poder incrível que temos no Flutter. O título já entrega o "spoiler" do que está por vir! Então vamos lá!

Vamos entender primeiramente sobre o Navigator 2.0. Muitos de vocês já devem ter ouvido do componente Navigator que nos possibilita a navegação por rotas.

 Navigator.pushNamed(context,"/home);

A segunda forma de navegar no Flutter é através do navigator utilizando o MaterialPageRoute ou CupertinoPageRoute.

Navigator.push(
context, MaterialPageRoute(builder: (context) => HomePage()));

Com essa introdução do Navigator 1.0 podemos adentrar no novo mundo de navegação.

A grande diferença agora é que você controle as páginas baseado em um estado. E como isso pode ser melhor? Agora você pode controlar o roteamento de forma global, ou seja, sua aplicação pode ter agora um estado de Navigation, onde você consegue saber exatamente em qual ponto e quais rotas estão a Stack (Pilha) de páginas.

Para conseguirmos entender melhor, precisamos olhar para um widget chamado Navigator. Esse cara é responsável por fazer toda a navegação que você conhece hoje quando se inicia a sua aplicação com um MaterialApp.

Navigator 1.0

Navigator 2.0

Podemos analisar que o Navigator 2.0 elimina o initialRoute e o onGenerateRoute, passando agora a utilizar somente uma lista de páginas para funcionar. E qual o ganho disso? A principal vantagem é você controlar quem vai está na lista de páginas.

Temos várias formas de controlar a lista de páginas:

Utilizando if na lista:

Exibindo uma lista com controle de inserção e remoção

Agora temos o controle das nossas páginas através de uma lista, e utilizamos o bom e velho setState para atualizar a Stack.

Agora que começa a ficar interessante, porque se analisarmos friamente o código anterior podemos perceber que o roteamento simplificou, porque se quiser fazer um push (inserir na lista), basta adicionar a página que deseja na pages e a mágica irá acontecer.

Esse é um ponto crucial no entendimento do Navigator 2.0, ele funciona baseado em um estado, com isso muda completamente a figura do que podemos fazer. Pensa comigo, temos um fluxo de cadastro que envolve várias etapas, e para facilitar você cria uma gerência de estado global que armazena qual passo você se encontra. Agora você quer navegar para outras páginas baseado no estado preenchido atualmente, se você utilizar o Navigator 2.0 para fazer esse roteamento e trabalhar com inserção e remoção ou if e else na sua lista de páginas fica simples fazer essa implementação.

Para aquele dev mais avisado, percebe que para os widget filhos alterarem o estados do widget Pai precisamos de algum acesso na árvore, para isso vou apresentar um componente feito para esse tipo de demanda, o nome dele é NotificationListener. Vamos conhecer sobre esse cara.

Se analisarmos friamente o nome já podemos inferir que esse componente irá ouvir notificações e com isso podemos tomar decisões na nossa lista de pages. Para fazer uso desse componente precisamos informar qual tipo de Notification ele irá ouvir.

NoficationListener<Notification>();

Podemos criar a nossa Notification personalizada fazendo uma extends.

class Nav2Notification extends Notification{}

Com isso, agora podemos implementar o nosso widget NoficiationListener.

Podemos analisar dois parâmetros no widget:

  • onNotification: Responsável por nós entregar a notificação
  • child: O widget a ser renderizado.

Para podermos disparar uma notificação precisamos simplesmente chamar a função dispatch(context) já implementada na classe Notification.

Nav2Notification().dispatch(context);

Simplesmente com esse comando e passando o contexto conseguimos mandar uma notifição para o widget Pai. Perceba o quão interessante é esse componente, através dele é possível fazer alterações no topo da árvore que contém o NoficiationListener. Agora te pergunto uma coisa, será que precisamos de packages de gerência de estado para todas as implementações na nossa aplicação? Será que as ferramentas já existentes no Flutter já podem suprir nossas necessidades?

Deixo as perguntas para você se questionar…

Recapitulando, estamos utilizando o Navigator 2.0 com a forma de inserção e remoção da lista e chamando o setState para atualizar a tela. Agora juntando o útil ao agradável, que é a possibilidade do widget filho atualizar o widget pai através do Nofication, podemos criar o nosso próprio sistema de Navigation 2.0 !

Para deixar a navegação bem próxima com o Navigator 1.0, iremos criar mais duas novas classes.

Como já estamos acostumados a chamar o push() para inserir uma página, utilizaremos o mesmo nome para essa classe que extende da Nav2Notification.

E para completar não poderia faltar o nosso conhecido pop() para remover a última página inserida na nossa Stack.

Agora a cereja do bolo, para deixar daquele jeito fácil de utilizar iremos criar mais uma classe Navigator2.

Facilitando o uso, de forma que para navegar basta chamar:

Navigator2.push(context,page:YourPage());

Como finalizamos a nossa classe Navigator2, precisamos alterar o NotificationListener para tratar essas notificações e tomar as decisões necessárias.

Agora podemos ouvir as notificações para inserir e remover da lista de páginas. Com essa parte pronta, só precisamos inserir o nosso widget Navigator para começar a fazer o roteamento.

Pronto! Agora temos uma integração maravilhosa entre o Navigator 2.0 e nosso querido NotificationListener.

Agora que temos a nossa implementação do Nav2, podemos focar na aplicação, como podemos utilizar esse componente de forma global? Simples, basta colocar ele no MaterialApp().

No exemplo crio duas páginas, HomePage() e ProfilePage().

Olha como ficou simples a navegação na HomePage() para o ProfilePage() simplesmente chamando uma função.

Podemos ver que a navegação junto com suas animações continua funcionando normalmente.

Obrigado por sua leitura!

E não pare por aqui, lá no meu canal tem vários tutoriais sobre o mundo do Flutter esperando por você!

Youtube

Repositório

--

--