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.