DEV Community

loading...
Cover image for  Utilizando o  Jetpack Navigation em projetos multi módulos

Utilizando o Jetpack Navigation em projetos multi módulos

1jgabriel profile image João Gabriel ・5 min read

Neste artigo, mostrarei como utilizar o Navigation, em um projeto modularizado.

O Navigation é um componente que faz parte do Jetpack e que consiste de três partes principais:

  • NavGraph: é um XML que centraliza as informações de navegação de uma feature.

  • NavHost: é um contêiner vazio que mostra destinos do gráfico de navegação. O componente de navegação contém uma implementação NavHost padrão, NavHostFragment, que mostra os destinos do fragment.

  • NavController: é um objeto que gerencia a navegação do aplicativo em um NavHost. O NavController organiza a troca do conteúdo de destino, no NavHost, conforme os usuários navegam pelo aplicativo.

Texto completo aqui.

Porque utilizar o Navigation?

Com o Navigation é possível ver toda a navegação através do NavGraph, não sendo necessário procurar por cada Intent e FragmentTransaction no projeto. Além disso, ele permite encontrar todos os destinos possíveis.

Um outro ponto positivo, é que não é mais necessário se preocupar com o fato do botão "voltar" sair do aplicativo ao vir de um deep link. Em relação ao deep link, vale salientar que ele também tem essa informação da navegação.

Segurança ao passar argumentos utilizando o SafeArgs. Não é mais necessário fazer verificações e proteções de segurança, porque é possível ter os argumentos com tipos definidos.

Ele também funciona com os padrões atuais da interface do usuário de navegação, como bottom-navigation, com apenas algumas configurações.
É possível também criar transições e animações 💙 entre a navegação.

Pré requisitos

Para utilizar o Navigation é necessário ter instalado o Android Studio na versão 3.3 ou superior.

E adicionar no build.gradle do projeto as dependências do navigation:

  implementation "androidx.navigation:navigation-fragment-ktx:2.2.2"
  implementation "androidx.navigation:navigation-ui-ktx:2.2.2"

No momento da criação deste artigo a versão mais recente é a 2.2.2.

Em projetos monolitos, temos todas as features e camadas em um único módulo, mas nem todas features precisam uma das outras, isso também se aplica a navegação.

Hands On

Como exemplo, temos uma feature 1 que tem 2 fragments e faz a navegação de Fragment A -> Fragment B

Feature 1 exemplo

Utilizando o navigation, precisaremos apenas de um NavGraphcom nossos 2 destinos e um action que leva do Fragment A ao Fragment B

Nav Graph Feature 1

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/nav_feature_one"
    app:startDestination="@id/fragment_a">

    <fragment
        android:id="@+id/fragment_a"
        android:name="io.jgabriel.featureone.FragmentA">

        <action
            android:id="@+id/navigate_to_b"
            app:destination="@+id/fragment_b"
            app:popUpTo="@+id/fragment_a" />
    </fragment>
    <fragment
        android:id="@+id/fragment_b"
        android:name="io.jgabriel.featureone.FragmentB"/>

</navigation>

Assim, temos a navegação da nossa primeira feature.


Agora iremos aumentar a nossa aplição incluindo mais 2 feature modules :
Project Tree

Dessa maneira, nossa aplicação conterá essas features e fragments:

All Features

Será necessário também adicionar os NavGraphspara as novas features, criadas seguindo o mesmo modelo da Feature 1

Feature two nav graph

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/nav_feature_two"
    app:startDestination="@id/fragment_c">

    <fragment
        android:id="@+id/fragment_c"
        android:name="io.jgabriel.featuretwo.FragmentC">

        <action
            android:id="@+id/navigate_to_d"
            app:destination="@+id/fragment_d"
            app:popUpTo="@+id/fragment_c" />
    </fragment>
    <fragment
        android:id="@+id/fragment_d"
        android:name="io.jgabriel.featuretwo.FragmentD"/>

</navigation>

Feature two nav graph

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/nav_feature_three"
    app:startDestination="@id/fragment_e">

    <fragment
        android:id="@+id/fragment_e"
        android:name="io.jgabriel.featurethree.FragmentE">

        <action
            android:id="@+id/navigate_to_"
            app:destination="@+id/fragment_f"
            app:popUpTo="@+id/fragment_e" />
    </fragment>
    <fragment
        android:id="@+id/fragment_f"
        android:name="io.jgabriel.featurethree.FragmentF" />
</navigation>

Precisamos adicionar as nossas feature ao módulo de aplicação através do build.gradle

Module app


implementation project(":featureone")
implementation project(":featuretwo")
implementation project(":featurethree")

Agora o nosso módulo de aplicação conhece as nossas 3 features.


Para não precisar repetir toda a navegação feita em cada feature, vamos reutilizar os NavGraphs, através da tag de include dentro do NavGraph do nosso módulo e aplicação

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/nav_main"
    app:startDestination="@id/nav_feature_one">

    <include app:graph="@navigation/nav_feature_one" />
    <include app:graph="@navigation/nav_feature_two" />
    <include app:graph="@navigation/nav_feature_three" />
</navigation>

Agora é possível fazer a navegação de qualquer fragment dentro do módulo de aplicação.


Em problemas reais, geralmente precisamos acessar um fragment de uma feature, através de outra, por exemplo:

O Fragment B, que está na Feature 1, precisa navegar até o Fragment D, que está na Feature 2:

Navigate fragment b to d

Para isso vamos adicionar deep links aos fragments e fazer a navegação através deles. Assim, as features continuarão independentes e o módulo de app será o responsável por gerenciar essa navegação.

NavGraph Feature Two

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/nav_feature_two"
    app:startDestination="@id/fragment_c">

    <fragment
        android:id="@+id/fragment_c"
        android:name="io.jgabriel.featuretwo.FragmentC">

        <action
            android:id="@+id/navigate_to_d"
            app:destination="@+id/fragment_d"
            app:popUpTo="@+id/fragment_c" />
    </fragment>
    <fragment
        android:id="@+id/fragment_d"
        android:name="io.jgabriel.featuretwo.FragmentD">
        <deepLink app:uri="navApp://fragmentD" />
    </fragment>

</navigation>

Utilizando a tag deepLink, podemos especificar o URI que podemos usar para navegar para esse destino específico, sem a

Feature One precisar conhecer a nossa Feature Two.

Para fazer essa navegação, vamos adicionar um click no FragmentB que vai navegar até o FragmentD

class FragmentB : Fragment() {
    fun onViewCreated(...) {
        ...
        ...
        view.setOnClickListener { 
            val uri = Uri.parse("navApp://fragmentD")
            findNavController().navigate(uri)
        }
   }
}

Dessa forma, mantemos os nossos módulos independentes um dos outros, e capazes de navegarem entre si.


Obrigado por ler até aqui. Todo o código utilizado está disponível em:

GitHub logo 1jGabriel / Navigation-multi-module

Navegação utilizando deeplink em um projeto modularizado

Discussion (0)

pic
Editor guide