DEV Community

Cover image for Replace fragment tag with FragmentContainerView Causing Runtime Error
Vincent Tsen
Vincent Tsen

Posted on • Updated on • Originally published at vtsen.hashnode.dev

Replace fragment tag with FragmentContainerView Causing Runtime Error

Because it fails to find navigation controller in your activity class

This article was originally published at vtsen.hashnode.dev on Dec 4, 2021.

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" />
Enter fullscreen mode Exit fullscreen mode

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" />
Enter fullscreen mode Exit fullscreen mode

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)
}
Enter fullscreen mode Exit fullscreen mode

After

private val navController by lazy {
    val navHostFragment = supportFragmentManager
        .findFragmentById(R.id.nav_host_fragment) as NavHostFragment

    navHostFragment.navController
}
Enter fullscreen mode Exit fullscreen mode

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?

See Also

Discussion (0)