Alura > Cursos de Mobile > Cursos de Android > Conteúdos de Android > Primeiras aulas do curso Navigation parte 1: transição de telas no Android

Navigation parte 1: transição de telas no Android

Migrando lista de notícias para fragment - Introdução

Olá pessoal, eu sou Alex Felipe, instrutor da Alura, e trago para vocês o primeiro curso de Architecture Components Navigation. Durante esse curso, usaremos como exemplo um aplicativo que simula uma loja online de artigos esportivos, chamada Alura Esporte. Nela, como tela inicial, teremos uma lista de produtos, contendo "Bola de futebol", "Camisa", "Chuteira" e "Bermuda". Ao clicarmos em um produto, teremos acesso à tela de detalhes dele (mostrando o nome do produto e o valor) e a um botão "Comprar" que leva à tela de pagamento.

Nessa tela, é exibido o valor a ser pago, os campos que deverão ser preenchidos com os dados do cartão e um botão "Confirmar pagamento" que efetua a compra e leva o usuário de volta à lista de produtos.

Perceba que o fluxo é bem simples, mas perceberemos que a implementação inicial do aplicativo considera uma arquitetura na qual temos apenas uma única activity e com telas representadas apenas por fragmentes. Aprenderemos, então, com quais detalhes teremos que lidar nesse tipo de implementação.

Em seguida, aprenderemos que existe uma biblioteca chamada Navigation, criada pela equipe de desenvolvedores do Android, que tem o objetivo de nos auxiliar nesse tipo de abordagem. O Navigation faz parte do pacote de bibliotecas do Android JetPack, que também possui outros componentes de arquitetura (architecture components), como LiveDate, ViewModel, Room, entre outros.

Na página do Jetpack, o Navigation é definido como "Gerencie tudo o que é necessário para a navegação no aplicativo". Ou seja, essa biblioteca nos orientará em qualquer tipo de dificuldade relacionada às configurações de navegação. Teremos alguns desafios para entender o seu funcionamento, mas garanto que, superados esses desafios, você gostará bastante dessa biblioteca.

Nesse primeiro curso, o foco será realmente entendermos a parte mais introdutória da Navigation, desde como ela pode ser adicionada ao nosso projeto, como configuramos o grafo de navegação ("navigation graph"), qual a ideia do hospedeiro de navegação, como é possível removermos a responsabilidade do activity e trabalhar somente com navigation, fazendo com que os fragments se comuniquem diretamente entre eles, entre outras coisas.

Na parte de configuração do grafo, entenderemos o que é destino, o que são ações e como é feita toda a configuração para atender o básico do Navigation, seja em projetos simples ou mais complexos. Essa base nos servirá de ponto de entrada nessa poderosa biblioteca de navegação.

Por padrão, o Navigation segue os princípios de navegação do próprio Android, cujos detalhes podem ser encontrados na documentação do Android.

Como esse é um curso introdutório, abordaremos uma parte mais básica do Navigation. Continuaremos avançando com o conteúdo em um segundo curso, portanto não fique preocupado caso algum tópico esteja faltando!

Vamos começar?

Migrando lista de notícias para fragment - Conhecendo o projeto

Como primeiro passo, vamos entender o funcionamento do nosso projeto, tanto na parte de features quanto na implementação de código. Dessa maneira, identificaremos o cenário atual e como o Navigation, o componente que estudaremos nesse curso, acabará nos ajudando.

O projeto é uma simulação de loja online de produtos esportivos chamada Alura Esporte. Na primeira tela, temos uma lista de produtos com o preço de cada um deles:

Bola de futebol R$100,00

Camisa R$80,00

Chuteira R$120,00

Bermuda R$60,00

Se clicamos em um desses elementos, vamos para uma tela de detalhes do produto. Nela, o nome do produto e o valor são apresentados em uma fonte maior, e na parte de baixo da tela temos um botão de "Comprar". Clicando nele, temos acesso à ultima tela, que é a tela de pagamento. Essa tela possui o valor do produto e campos para serem preenchidos com os dados do cartão (número, data de validade e código de verificação). Como se trata de uma simulação e não existem validações ou integrações com algum tipo de API de pagamento, esses campos podem ser preenchidos livremente. Clicando em "confirmar", a mensagem "Compra realiza" é exibida na tela. Esse é o cenário normal no fluxo do nosso aplicativo.

Agora que entendemos a parte visual, vamos analisar como funciona o nosso código e quais são as peculiaridades que poderemos melhor. Antes de tudo, é importante ressaltar que estamos mantendo a arquitetura que vimos no curso de Architecture Components, representada pelo diagrama abaixo.

Como a imagem mostra, na nossa aplicação teremos Activities/Fragments, ViewModels, LiveData, repositórios, e, especificamente aqui, trabalharemos diretamente com um banco de dados interno, sem integração com uma Web API (para evitarmos maiores complexidades no projeto). Com exceção desse último ponto, o núcleo do nosso projeto é o apresentado no diagrama.

Tendo entendido a estrutura, vamos analisar a implementação. Se queremos ver a tela de lista de produtos, podemos acessar o nosso source set do java br.com.alura.aluraesporte. Dentro desse diretório, teremos nossa ui os nossos fragments, onde estarão representadas as telas.

Sendo assim, teremos um fragment para lista de produtos, outro para tela de pagamento, outro para detalhes do produto e assim por diante. Cada tela é representada por um fragment, e, consequentemente, teremos apenas uma activity mantendo essas telas.

Como comentamos no curso de fragments, existe a possibilidade de criar aplicativos com vários fragments e uma única activity. No curso atual, optamos por essa amostra justamente para mostrar como seria essa implementação.

Em ProdutosActivity, por mais que tenhamos os detalhes de cada um dos produtos, temos também o pagamento - o que não faz muito sentido com base nesse nome. Porém, isso é apenas para termos essa demonstração, e iremos refatorar o código no futuro.

private const val COMPRA_REALIZADA = "Compra realizada"

class ProdutosActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.produtos_activity)
        if (savedInstanceState == null) {
            val produtosFragment: ListaProdutosFragment by inject()
            transacaoFragment {
                replace(R.id.container, produtosFragment)
            }
        }
    }

    override fun onAttachFragment(fragment: Fragment?) {
        super.onAttachFragment(fragment)
        when (fragment) {
            is ListaProdutosFragment -> {
                fragment.quandoProdutoSelecionado = { produtoSelecionado ->
                    val detalhesProdutoFragment: DetalhesProdutoFragment by inject()
                    val argumentos = Bundle()
                    argumentos.putLong(CHAVE_PRODUTO_ID, produtoSelecionado.id)
                    detalhesProdutoFragment.arguments = argumentos
                    transacaoFragment {
                        addToBackStack(null)
                        replace(R.id.container, detalhesProdutoFragment)
                    }
                }
            }
            is DetalhesProdutoFragment -> {
                fragment.quandoProdutoComprado = { produtoComprado ->
                    val pagamentoFragment: PagamentoFragment by inject()
                    val dado = Bundle()
                    dado.putLong(CHAVE_PRODUTO_ID, produtoComprado.id)
                    pagamentoFragment.arguments = dado
                    transacaoFragment {
                        addToBackStack(null)
                        replace(R.id.container, pagamentoFragment)
                    }
                }
            }
            is PagamentoFragment -> {
                fragment.quandoPagamentoRealizado = {
                    Toast.makeText(this, COMPRA_REALIZADA, Toast.LENGTH_LONG).show()
                }
            }
        }
    }

}

No começo, criamos a nossa lista de produtos (ListaProdutosFragment) e fazemos as configurações via onAttachFragment para pegarmos os listeners - temos o listener para a lista de produtos, outro para detalhes do produto e outro para o pagamento. Quanto mais criamos fragments para mantermos uma única activity principal, mais aumentamos a complexidade de implementação desses listeners.

Uma tela mais complexa, com vários botões e vários listeners, nossa activity será muito grande, e manter esse código acabará sendo não trivial. Pensando nesse tipo de implementação, temos a alternativa de utilizar um componente chamado Navigation. Mas como ele pode melhorar a nossa experiência?

O Navigation vem com a proposta de implementar um aplicativo com vários telas considerando uma única activity, da mesma maneira que vimos no nosso projeto. A diferença é que isso será uma experiência mais fácil para quem desenvolve aplicativos, nos permitindo um resultado diferente daquele obtido quando mantemos todo o código na activity e sem uma visualização das interações possíveis.

Inclusive, o Navigation, por padrão, tem uma proposta interessante de seguir os princípios de navegação dentro de um aplicativo. Essas e outras informações serão destrinchadas durante o curso.

Recapitulando: no cenário atual, temos um aplicativo muito simples que utiliza uma arquitetura aprendida em outros cursos, porém com a dificuldade de manter todo o código (diversos fragments) em uma única activity. Nosso objetivo é facilitar o desenvolvimento desse código com o Navigation.

Sinta-se à vontade para explorar o projeto e aprender mais sobre ele. Por exemplo, estamos utilizando injeção de dependência com coin, repositórios, room e outras tecnologias que já conhecemos nos cursos anteriores.

Um detalhe importante: no coin, fizemos duas instâncias do banco de dados - uma de teste e outra de produção. O objetivo da instância de teste é preencher os produtos, de forma que não precisaremos coloca-los manualmente. Também temos uma novidade, que são as Coroutines, uma abordagem para processamento paralelo (como se fossem threads, mas com uma certa diferença). Esse conteúdo será abordado nos exercícios do curso.

Se tiver com dúvidas em relação a alguma abordagem, não deixe de buscar o fórum do curso! A seguir conhecemos um pouco mais sobre a proposta do Navigation e outros detalhes teóricos para prosseguirmos com o curso.

Migrando lista de notícias para fragment - Entendendo os princípios de navegação

Vimos que o Navigation é um componente capaz de nos auxiliar na implementação de navegação entre telas no nosso aplicativo. Também vimos que ele utiliza por baixo dos panos os princípios de navegação dos aplicativos Android, mas o que exatamente isso significa? Quais benefícios eles trazem?

Tais princípios de navegação podem ser encontrados na página referente a esse tópico da documentação do Android. Na página, somos informados que, quando consideramos esses princípios de navegação entre telas, estaremos lidando com uma parte fundamental da experiência do usuário. Isso porque o usuário está acostumado a um certo padrão de navegação e espera determinados comportamentos nesse ambiente. Dessa forma, quando seguimos os princípios destacados, conseguimos entregar um aplicativo cujo uso é mais intuitivo.

Vamos analisar alguns pontos listados na documentação. O primeiro deles é sobre o destino inicial ser fixo. Mas o que isso significa? Observe o exemplo:

Nele, temos uma tela com o "Launcher", que é a lista de apps no Android, uma tela de lista e uma tela de detalhes, além de setas que indicam o processo de entrar em uma tela mais profunda e fazer o processo reverso com o botão de voltar, retornando ao Launcher. Isso não é novidade para quem usa aplicativos no dia-a-dia, mas trata-se, sim, de um principio de navegação.

O princípio do destino inicial fixo é justamente essa ideia: a primeira tela deverá ser a primeira e a última do processo de navegação do usuário. Inclusive, o nosso aplicativo já tem esse comportamento. O Navigation tem isso por padrão, eliminando essa preocupação do nosso desenvolvimento. Para termos esse comportamento, considerando a implementação de fragments, deveremos ficar atento à nossa backstack, por exemplo, pois dependendo da maneira que ela é construída os detalhes poderiam acabar como a última tela.

O próximo princípio postula que o estado de navegação é representado como uma pilha de destinos. Isso significa que cada vez que entramos em uma tela do nosso aplicativo, ela será considerada uma task. Como já comentamos anteriormente, temos uma lista/pilha de tarefas que vai se acumulando na próxima tela, que se torna a task principal (no topo dessa lista/pilha).

Isso é importante pois, quando avançamos uma tela, estamos mantendo a nossa backstack. Sendo assim, se queremos voltar da tela de pagamento da nossa aplicação para a tela de detalhes, basta a removermos do topo. Da mesma forma, se quisermos voltar para a lista, bastará removermos a tela de detalhes do topo.

Hoje nossa aplicação já mantém esse comportamento, já que ele é esperado por qualquer tipo de aplicativo, e o Navigation também manterá essa abordagem por padrão - que nada mais é do que um histórico de interações do usuário com um aplicativo.

Esses princípios não são uma novidade no desenvolvimento das nossas aplicações, mas precisamos tomar bastante cuidado para manter esses comportamentos quando fazemos a implementação via fragments. A utilização do Navigation nos trará um pouco mais de tranquilidade em relação a esses e outros tópicos, já que ele segue tais recomendações por padrão.

Além dos princípios listados, outros temas são abordados na documentação, como os botões de "up" e "back" e a lógica do deep linking, que são telas que podem ser acessadas diretamente sem passar por todo o fluxo.

Agora que entendemos a importância dos princípios de navegação, no próximo vídeo começaremos a implementar o Navigation no nosso projeto.

Sobre o curso Navigation parte 1: transição de telas no Android

O curso Navigation parte 1: transição de telas no Android possui 128 minutos de vídeos, em um total de 38 atividades. Gostou? Conheça nossos outros cursos de Android em Mobile, ou leia nossos artigos de Mobile.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Android acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas