Replace fragment tag with FragmentContainerView Causing Runtime Error

Because it fails to find navigation controller in your activity class

ยท

1 min read

Replace fragment tag with FragmentContainerView Causing Runtime Error

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_with_fragment_container_view_01.PNG

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.

replace_with_fragment_container_view_02.PNG

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?

ย