segunda-feira, 2 de maio de 2016

Aplicando o padrão de projeto State para gerenciar fragments. - PARTE 1


   
É comum acontecer problemas quando tentamos criar um fluxo de telas utilizando fragments em mais de 1 conteiner. As vezes não conseguimos entender como podemos mostrar um fragment por cima de outro fragment e qual a melhor maneira de exibir o fragment que estava sendo exibido antes do fragment atual.
Esse gerenciamento pode acabar levando você a criar vários if/else ou um enorme switch case o que não é um boa prática pois diminui a manutenibilidade, além de sujar seu código.

Como exemplo iremos criar um aplicativo simples que terá apenas uma activity e dois containers onde ficaram armazenados os fragments

Colocando em imagens fica mais claro para entender a estrutura do layout que armazenará os fragments:
A ideia é que sejá possível usar os dois containers para exibir os fragments e que cada fragment saiba onde vai ser exibido.
Mas por que usar fragments que serão exibidos um por cima do outro?
Com a popularização dos fragments, um aplicação pode conter diversos fragments e eles podem ser adicionados em vários containers e se a troca de fragments não for bem orquestrada, isso pode causar diversos problemas como, fragments que aparecem em lugares errados ou não aparecem e você não entende o que aconteceu.

Depois de quebrar a cabeça por bastante tempo consegui chegar em uma solução utilizando uma das melhores invenções do Java( Na minha opinião ), Enum.
O Enum aliado ao padrão de projeto State, pode ser um ferramenta poderosa para controle de fluxos, pois com essa dupla é possivel definir qual o próxima tela que devo ir,  baseado na tela atual e caso eu tente ir para uma tela errada!! BUMM!, Exception in your face!!!.

Resumindo de forma bem rápido o que é o padrão de projeto State. Ele tem como principal objetivo definir qual o próximo comportamento/estado de um objeto baseado no comportamento/estado atual garantindo assim que todo fluxo pré-definido será respeitado.

Quero demonstrar como eu consegui fazer um workaround para evitar estes problemas.
A aplicação terá apenas 6 telas, mas ao final do projeto, será possível adicionar novas telas(fragments) sem muito trabalho.

O video abaixo demonstra como o app funcionará.


Fluxo das telas.

As telas serão:
Splash, Login, Sign Up, Home, Settings e User Settings
E seguirão as seguintes regras:




A estrutura do projeto se baseia nas seguintes classes:

1. MainActivity.java -> Activity que contém os dois containers (LinearLayouts) dos fragments.
2. PageManager.java -> Classe que será responsável pela navegação dos fragments.
3. PageId.java -> Enum onde será aplicado o padrão State.
4. TransitionPageConfig.java -> Classe que representará a *configuração da transição (Tela Atual -> Próxima Tela).
5. Fragments que representarão cada tela da aplicação

*As configurações de tela serão:

1. Qual o fragment da tela.
2. Em qual container ela irá aparecer (fragment_container_1 out fragment_container_2).
3. Qual será a animação de saída do fragment atual e a animação de entrada do próximo fragment?
4. Qual será a próxima tela a ser exibida?
5. É preciso remover a tela atual?
6. É preciso alterar a próxima tela?

Mão na massa!!
“Uma caminhada de mil léguas começa com o primeiro passo”, diz o filosofo… 
“int main(){“, diz o programador.

Começaremos pelo Enum onde será aplicado o padrão State.

Começaremos definindo os ids referentes as telas:


Em seguida vamos dar a cada enum dele dois atributos um Fragment, e um inteiro que será o id do container  onde o fragment irá ser adicionado e seus respectivos getters:


Perceba que eu adicionei também um construtor que recebe como parâmetro o id do container. Ao fazer isso cada tela do enum terá que passar como construtor o Id, ficando desse jeito:


Todos os fragments utilizados na aplicação herdam de BaseFragment, que contém um Listener e será usado no PageManager.java para indicar quando o fragment foi destruido.





Agora vamos modificar o método getFragment() e criar o um método abstrato getFragmentInstance() que será implementado por cada item;

Ok, até agora vimos como utilizar o Enum para montar nossa configuração dos fragments, deixando assim o código mais limpo e organizado.

No próximo post irei mostrar como utilizaremos esse Enum para aplicarmos na prática o padrão State.

Nenhum comentário:

Postar um comentário