IllegalArgumentException: navigation destination xxx is unknown to this NavController

后端 未结 30 2104
遇见更好的自我
遇见更好的自我 2020-11-27 11:28

I am having issue with the new Android Navigation Architecture component when I try to navigate from one Fragment to another, I get this weird error:

相关标签:
30条回答
  • 2020-11-27 12:07

    It could also happen if you have a Fragment A with a ViewPager of Fragments B And you try to navigate from B to C

    Since in the ViewPager the fragments are not a destination of A, your graph wouldn't know you are on B.

    A solution can be to use ADirections in B to navigate to C

    0 讨论(0)
  • 2020-11-27 12:08

    What I did to prevent the crash is the following:

    I have a BaseFragment, in there I've added this fun to ensure that the destination is known by the currentDestination:

    fun navigate(destination: NavDirections) = with(findNavController()) {
        currentDestination?.getAction(destination.actionId)
            ?.let { navigate(destination) }
    }
    

    Worth noting that I'm using the SafeArgs plugin.

    0 讨论(0)
  • In my case, the issue occurred when I had re-used one of my Fragments inside a viewpager fragment as a child of the viewpager. The viewpager Fragment(which was the parent fragment) was added in the Navigation xml, but the action was not added in the viewpager parent fragment.

    nav.xml
    //reused fragment
    <fragment
        android:id="@+id/navigation_to"
        android:name="com.package.to_Fragment"
        android:label="To Frag"
        tools:layout="@layout/fragment_to" >
        //issue got fixed when i added this action to the viewpager parent also
        <action android:id="@+id/action_to_to_viewall"
            app:destination="@+id/toViewAll"/>
    </fragment>
    ....
    // viewpager parent fragment
    <fragment
        android:id="@+id/toViewAll"
        android:name="com.package.ViewAllFragment"
        android:label="to_viewall_fragment"
        tools:layout="@layout/fragment_view_all">
    

    Fixed the issue by adding the action to the parent viewpager fragment also as shown below:

    nav.xml
    //reused fragment
    <fragment
        android:id="@+id/navigation_to"
        android:name="com.package.to_Fragment"
        android:label="To Frag"
        tools:layout="@layout/fragment_to" >
        //issue got fixed when i added this action to the viewpager parent also
        <action android:id="@+id/action_to_to_viewall"
            app:destination="@+id/toViewAll"/>
    </fragment>
    ....
    // viewpager parent fragment
    <fragment
        android:id="@+id/toViewAll"
        android:name="com.package.ViewAllFragment"
        android:label="to_viewall_fragment"
        tools:layout="@layout/fragment_view_all"/>
        <action android:id="@+id/action_to_to_viewall"
            app:destination="@+id/toViewAll"/>
    </fragment>
    
    0 讨论(0)
  • 2020-11-27 12:10

    It occurs to me when I press the back button two times. At first, I intercept KeyListener and override KeyEvent.KEYCODE_BACK. I added the code below in the function named OnResume for the Fragment, and then this question/issue is solved.

      override fun onResume() {
            super.onResume()
            view?.isFocusableInTouchMode = true
            view?.requestFocus()
            view?.setOnKeyListener { v, keyCode, event ->
                if (event.action == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_BACK) {
                    activity!!.finish()
                    true
                }
                false
            }
        }
    

    When it happens to me for a second time, and it's status is the same as the first one, I find that I maybe use the adsurd function. Let’s analyze these situations.

    1. Firstly, FragmentA navigates to FragmentB ,then FragmentB navigates to FragmentA, then press back button... the crash appears.

    2. Secondly, FragmentA navigates to FragmentB, then FragmentB navigates to FragmentC, FragmentC navigates to FragmentA, then press back button... the crash appears.

    So I think when pressing back button, FragmentA will return to FragmentB or FragmentC, then it causes the login mess. Finally I find that the function named popBackStack can be used for back rather than navigate.

      NavHostFragment.findNavController(this@TeacherCloudResourcesFragment).
                            .popBackStack(
                                R.id.teacher_prepare_lesson_main_fragment,false
                            )
    

    So far, the problem is really solved.

    0 讨论(0)
  • 2020-11-27 12:11

    Check currentDestination before calling navigate might be helpful.

    For example, if you have two fragment destinations on the navigation graph fragmentA and fragmentB, and there is only one action from fragmentA to fragmentB. calling navigate(R.id.action_fragmentA_to_fragmentB) will result in IllegalArgumentException when you were already on fragmentB. Therefor you should always check the currentDestination before navigating.

    if (navController.currentDestination?.id == R.id.fragmentA) {
        navController.navigate(R.id.action_fragmentA_to_fragmentB)
    }
    
    0 讨论(0)
  • 2020-11-27 12:11

    Updated @Alex Nuts solution

    If there is no action for particular fragment and want to navigate to fragment

    fun NavController.navigateSafe(
    @IdRes actionId: Int, @IdRes fragmentId: Int, args: Bundle? = null,
    navOptions: NavOptions? = null, navExtras: Navigator.Extras? = null) 
    {
      if (actionId != 0) {
          val action = currentDestination?.getAction(actionId) ?: graph.getAction(actionId)
          if (action != null && currentDestination?.id != action.destinationId) {
              navigate(actionId, args, navOptions, navExtras)
        }
        } else if (fragmentId != 0 && fragmentId != currentDestination?.id)
            navigate(fragmentId, args, navOptions, navExtras)
    }
    
    0 讨论(0)
提交回复
热议问题