Skip to main content

Command Palette

Search for a command to run...

Replace fragment tag with FragmentContainerView Causing Runtime Error

Because it fails to find navigation controller in your activity class

Updated
1 min read
Replace fragment tag with FragmentContainerView Causing Runtime Error
V

I'm a self-taught hobbyist Android developer who loves to build projects and share valuable tips for new Android developers.

Feel free to comment, share or connect with me!

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?

Android App Dev

Part 42 of 47

Discover helpful tips and tricks for Android app development and Jetpack Compose through my personal journey and experience.

Up next

DataBindingUtil.inflate vs View Binding Inflate

You can inflate your fragment views either with data binding or view binding. Which one should be used?