Home > database >  Navigating back in a multi-module Android application
Navigating back in a multi-module Android application

Time:12-31

I'm currently working on a multi-module application which is structured as below and I can't get the back navigation to function correctly when navigating between feature modules. Either nothing happens or the app closes instead of just going back to the previous destination.

- app
- feature-explore
- feature-search
- feature-detail

Each of the feature modules has it's own navigation graph which is brought together in the main navigation graph located in the app module. The app module contains a single MainActivity with a FragmentContainerView and BottomNavigationView in its layout...

<?xml version="1.0" encoding="utf-8"?>
<layout 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">

    <data>

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".ui.MainActivity">

        <com.google.android.material.bottomnavigation.BottomNavigationView
            android:id="@ id/main_bottomnav"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:menu="@menu/menu_bottomnav" />

        <androidx.fragment.app.FragmentContainerView
            android:id="@ id/main_navhost"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:defaultNavHost="true"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:navGraph="@navigation/nav_main" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

The BottomNavigationView is linked to a menu to hook up feature-explore and feature-search modules as main destinations with their own navigation graphs...

class MainActivity : AppCompatActivity() {
    
    private lateinit var navController: NavController
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        val binding = ActivityMainBinding.inflate(LayoutInflater.from(this))
        setContentView(binding.root)

        navController = (supportFragmentManager.findFragmentById(R.id.main_navhost) as NavHostFragment).navController

        binding.mainBottomnav.setupWithNavController(
            navController
        )
    }
}

I've then set up a global action in the main navigation graph to allow each of the feature-explore and feature-search modules to navigate to the feature-detail module (e.g. clicking an item in a list opens up the detail of that item via a separate feature module).

This is the main navigation 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"
    android:id="@ id/nav_main"
    app:startDestination="@id/nav_explore">

    <include app:graph="@navigation/nav_detail" />
    <include app:graph="@navigation/nav_explore" />
    <include app:graph="@navigation/nav_search" />


    <action
        android:id="@ id/action_global_nav_detail"
        app:destination="@id/nav_detail">

        <argument
            android:name="id"
            app:argType="long" />
    </action>

</navigation>

Switching between menu items works fine as does navigating using the global action above to move to the nav_detail graph.

From the fragment in that nav_detail graph though I would expect the device back button to take the user back to the previous view in the back stack. Instead nothing happens and the user stays on the detail fragment (the start destination of nav_detail).

If I update the global action to specify a popUpTo value then MainActivity is closed altogether...

<action
    android:id="@ id/action_global_nav_detail"
    app:destination="@id/nav_detail"
    app:popUpTo="@id/nav_explore"
    app:popUpToInclusive="false">

    <argument
        android:name="id"
        app:argType="long" />
</action>

Anyone have any suggestions on how the get the back navigation from nav_detail to behave as expected?

Note - I'm using Navigation Components v2.5.3.

CodePudding user response:

After further investigation I found that the issue wasn't actually to do with the navigation itself. The back press was actually going back to the previous fragment.

I was however using LiveData to hold an ID of the selected item and, as the view model and the LiveData value was retained, it was observed again immediately after navigating back and therefore navigated to the detail fragment again.

See similar issue here with a link to options for changing approach with the LiveData to avoid this problem.

  • Related