Replace fragment tag with FragmentContainerView Causing Runtime Error
Because it fails to find navigation controller in your activity class
You have fragment defined in your main activity layout xml file.
<fragment
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph" />
Android studio gives you the following warning.
Replace the tag with FragmentContainerView.
You follow the suggestion and replace it with androidx.fragment.app.FragmentContainerView
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph" />
Then, you can build the project successfully. However, when you run it, your app crashes with the following run-time error.
Caused by: java.lang.IllegalStateException: Activity com.udacity.shoestore.ui.MainActivity@f2c4e66 does not have a NavController set on 2131362101 at androidx.navigation.Navigation.findNavController(Navigation.java:61)
Solution
findNavController()
no longer works in your activity class. You need to find the fragment first, using supportFragmentManager.findFragmentById()
to access the navigation controller.
Before
private val navController by lazy {
findNavController(R.id.nav_host_fragment)
}
After
private val navController by lazy {
val navHostFragment = supportFragmentManager
.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
navHostFragment.navController
}
Conclusion
I'm not exactly sure why FragmentContainerView
should be used, even after I read the documentation. Personally, from a user perspective, I prefer using <fragment>
tag because it uses less code to find the navigation controller. The app also runs perfectly fine with it!
Also, the default template project from Android Studio does NOT use <androidx.fragment.app.FragmentContainerView>
which it should if that is the recommended way?