DEV Community

Mohamed Shalan
Mohamed Shalan

Posted on

Android Navigation Component Issue

I had an issue in the application I am currently working on it followed the following scenario; Question on stackoverflow

There is an activity, let's call it PaymentFlowActivity. This activity has only 3 fragments; shipping, review and payment fragment and it doesn't have a NavHostFragment.

In the Shipping Fragment, I have more than one state, so I decided to add a NavHostFragment for this fragment to handle back stack for those different states.

so in my fragment layout file, I did the following

<androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/root_view">

        <fragment
            android:id="@+id/shipping_host_nav"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:navGraph="@navigation/shipping_nav_graph"
            app:defaultNavHost="true"/>
<androidx.constraintlayout.widget.ConstraintLayout/>
Enter fullscreen mode Exit fullscreen mode

And when I try to access the nav controller using findNavController() it throws the following exception

java.lang.IllegalStateException:xxxxxxxxxxxxx does not have a NavController set

when I searched for this exception, I didn't find any useful answers to this use case issue.

So, I went through the Navigation component code in the SDK and I found the following: when using the findNavController() with a fragment that isn't NavHostFragment or isn't within NavHostFragment this exception will be thrown.

So we have to find the nav controller by ourselves using the id of the nav host fragment defined in the fragment and the activity as follow

val navController = Navigation.findNavController(activity, R.id.shipping_host_nav)
Enter fullscreen mode Exit fullscreen mode

this will get the navController of your NavHostFragment defined in the fragment layout.

You can use the navController to navigate to the desired destination

navController.navigate(R.id.my_destenation) 
Enter fullscreen mode Exit fullscreen mode

To make it easier to get the nav controller, I made an extension function for the fragment class that enables accessing the nav controller using only the id.
Here is a snippet:

fun Fragment.getFragmentNavController(@IdRes id: Int) = activity?.let {
        return@let Navigation.findNavController(it, id)
}
Enter fullscreen mode Exit fullscreen mode

Then in your fragment, you can use this method to navigate to the desired destination.

getFragmentNavController(R.id.shipping_host_nav)
.navigate(R.id.action_new_address_to_addresses)
Enter fullscreen mode Exit fullscreen mode

Top comments (1)

Collapse
 
pablosiax profile image
Pablinux

please java code:
val navController = Navigation.findNavController(activity, R.id.shipping_host_nav)