【问题标题】:Navigation component Kotlin - cannot be found from the current destination导航组件 Kotlin - 无法从当前目的地找到
【发布时间】:2020-12-27 12:47:28
【问题描述】:

我有一个片段 A、B、C。从 A -> B 导航时没问题,但从 B -> C 会崩溃。

这是我的导航

这是我的导航代码

 categoryProductItemListAdapter.setOnItemClickListener {
        val action = CategoryProductItemsDirections.actionCategoryProductItems2ToProductItem(null, it)
        navController = Navigation.findNavController(requireView())
        navController?.navigateUp()
        navController?.navigate(action)
    }

这是 productItem 目的地的 XML 代码

<fragment
    android:id="@+id/categoryProductItems2"
    android:name="com.sample.store.main.dashboard.ui.ui.home.categoryitems.CategoryProductItems"
    android:label="CategoryProductItems"
    tools:layout="@layout/fragment_category_product_items">
    <argument
        android:name="category_global"
        app:argType="com.sample.store.data.globalmodels.response.categories.Category" />
    <action
        android:id="@+id/action_categoryProductItems2_to_productItem"
        app:destination="@id/productItem"
        app:enterAnim="@anim/enter_from_right"
        app:exitAnim="@anim/exit_to_right"
        app:popEnterAnim="@anim/fragment_open_enter"
        app:popExitAnim="@anim/fragment_fade_exit" />
</fragment>

这是错误:

java.lang.IllegalArgumentException: Navigation action/destination com.sample.store.full:id/action_categoryProductItems2_to_productItem cannot be found from the current destination Destination(id/navigation_home) label=Home class=com.sample.store.main.dashboard.ui.ui.home.mainui.HomeFragment

我不知道发生了什么,但似乎 navController 正在寻找“navigation_home”

【问题讨论】:

  • 你能分享完整的 nav_host.xml 文件吗
  • @Cyd 删除该行 `navController?.navigateUp()` 可能会解决您的问题

标签: android kotlin android-architecture-navigation


【解决方案1】:

对于我的情况,我通过替换来解决问题

implementation "android.arch.navigation:navigation-fragment-ktx:1.0.0"

implementation "androidx.navigation:navigation-fragment-ktx:2.3.5"

【讨论】:

    【解决方案2】:

    这更像是一个提醒而不是一个答案。但我希望它会有所帮助。

    总结:(正如其他人已经说过的那样:)对导航函数的连续调用是大多数这些异常的原因。

    鉴于 android 组件的结构,特别是 MediatorLiveData 的工作方式,人们有时可能希望将数据节点加入单个可观察数据持有者 (LiveData)。

    如果对该中介的观察与动态导航功能相关联,那么无疑会出现错误。

    原因是源可能会连续更改 LiveData 值的次数等于连接到调解器的源数量。

    这是一个非常好的主意,但是。反复更改 NavController 肯定会导致不良结果。

    这可能包括:

    • 两次弹出 backStack。

    • 从 A -> B 连续两次出现 A 未找到的异常
      第二次。

    这是一个很大的测试问题,特别是因为一个 Fragment 的问题可能会级联到底层堆栈,因此当一个 Fragment 中可能出现 Direction not found 异常时,真正的罪魁祸首可能在 TOP 的 Fragment 上给出例外的那个。

    实际上,这可以通过创建一个自取消线程执行器scheduled.cancel(true); 来轻松解决,该线程执行器对 mediatorLiveData 本身具有延迟容差(准确地说是 onChange,而不是 setValue(),因为急切的内部状态更新是全部且唯一的调解员恕我直言的目的/笑话(抱歉,不允许 postValue()!))。

    更不用说中介者本身就是一个不完整的组件……

    另一种更简单的方法是确保当且仅当 !Object::Equals 时才执行来自 MutableLiveData 的 onChange 调用,并防止重复调用 onChange(),这仍然是 MediatorLiveData/LiveData 不完整的证明。 (请务必小心使用列表)

    不惜一切代价避免对 NavController 执行连续调用,如果您必须这样做,那么延迟可运行可能是您实现它的唯一方法。

    【讨论】:

      【解决方案3】:

      我创建了一个扩展函数来检查从当前目的地开始一个动作的可行性。

      fun NavController.navigateSafe(@IdRes resId: Int, args: Bundle? = null) {
      val destinationId = currentDestination?.getAction(resId)?.destinationId.orEmpty()
      currentDestination?.let { node ->
          val currentNode = when (node) {
              is NavGraph -> node
              else -> node.parent
          }
          if (destinationId != EMPTY_INT) {
              currentNode?.findNode(destinationId)?.let { navigate(resId, args) }
          }
      }}
      

      【讨论】:

      • val destinationId = currentDestination?.getAction(resId)?.destinationId.orEmpty() 在这一行中,最后一个 .orEmpty() 是红色的。我不知道为什么。 if (destinationId != EMPTY_INT) { currentNode?.findNode(destinationId)?.let { navigate(resId, args) } } 并且在这种情况下 EMPTY_INT 是红色的,将在那里检查哪个值。指导我
      【解决方案4】:

      就我而言,我通过替换来解决问题 -

       <action
          android:id="@+id/action_categoryProductItems2_to_productItem"
          app:destination="@id/productItem"
          app:enterAnim="@anim/enter_from_right"
          app:exitAnim="@anim/exit_to_right"
          app:popEnterAnim="@anim/fragment_open_enter"
          app:popExitAnim="@anim/fragment_fade_exit"/>
      

       <action
          android:id="@+id/action_categoryProductItems2_to_productItem"
          app:destination="@id/productItem"
          app:enterAnim="@anim/enter_from_right"
          app:exitAnim="@anim/exit_to_right"
          app:popEnterAnim="@anim/fragment_open_enter"
          app:popExitAnim="@anim/fragment_fade_exit"
          app:popUpToInclusive="true" /* If true then also remove the destination from stack while popup */
          app:popUpTo="@id/navigation_home"/>  /*The fragment where to land again from destination*/
                   
      

      【讨论】:

        【解决方案5】:

        您需要设置 defaultNavHost="true"。就像在这个例子中一样:

        <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:orientation="vertical">
                    <androidx.fragment.app.FragmentContainerView
                        android:id="@+id/myNavHostFragment"
                        android:name="androidx.navigation.fragment.NavHostFragment"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"
                        app:defaultNavHost="true"
                        app:navGraph="@navigation/navigation_layout" />
                </LinearLayout>
        

        另外不要忘记在导航组件中设置主页活动。

        【讨论】:

          【解决方案6】:

          首先,当您尝试检索您的导航控制器时,您不应该传递requireView() - navController = Navigation.findNavController(requireView())。您应该传递实际的 Navigation Host Fragment 实例。

          第二个问题是因为您试图在片段 A 上从 B -> C 调用导航路径。

          你的方向路径是从 B -> C

          val action = CategoryProductItemsDirections.actionCategoryProductItems2ToProductItem(null, it)
          

          但是您首先向上导航,因此您在尝试执行导航时实际上位于片段 A 上:

          navController?.navigateUp()
          navController?.navigate(action)
          

          【讨论】:

          • 在处理像 ViewPager 这样的嵌套片段时,您很容易犯错误,试图从嵌套页面导航到另一个片段,而实际上必须从 ViewPager 片段导航到目标片段。
          • 有趣的评论,不确定查看寻呼机与这篇文章/问题有什么相关性?没有提到正在使用视图寻呼机
          • 您的回答帮助我解决了我在评论中提到的问题。也就是说,尝试从您当前不在的目的地导航。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-04-18
          • 1970-01-01
          • 2021-12-19
          • 2021-01-09
          • 1970-01-01
          • 2021-10-15
          相关资源
          最近更新 更多