由navGraphViewModels创建,创建java.lang.IllegalArgumentException:NavController的后堆栈上没有ID为<目标ID>的目标

问题描述

当配置发生更改并因此而重新创建我的“活动”和“片段”时,在再次创建“片段”时,我的导航图作用域viewmodel不可用。
似乎在navGraph之前重新创建了Fragment。

我正在使用以下代码从片段中初始化navGraph范围内的viewmodel:

private val myviewmodel: Myviewmodel by navGraphviewmodels(R.id.nav_graph_id)

如果我尝试在片段myviewmodel函数中使用onViewCreated,则在更改配置后会得到IllegalArgumentException。例外:

java.lang.IllegalArgumentException: No destination with ID <destination id> is on the NavController's back stack

我该如何处理?

I have already checked that my ID isn't used anywhere else.

Edit1:

这是我的activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    
    <androidx.fragment.app.FragmentContainerView
            android:id="@+id/main_nav_host"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:defaultNavHost="true"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:navGraph="@navigation/main_nav_graph" />

</androidx.constraintlayout.widget.ConstraintLayout>

这是我的main_nav_graph.xml:

<navigation
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/main_nav_graph"
        app:startDestination="@id/main_nav_graph_1">
    
    <navigation
            android:id="@+id/main_nav_graph_1"
            android:label="@string/nav_graph_1_label"
            app:startDestination="@id/nav_graph_1_start_fragment">
        <!-- nav graph stuff -->
    </navigation>
    
    <navigation
            android:id="@+id/main_nav_graph_2"
            android:label="@string/nav_graph_2_label"
            app:startDestination="@id/nav_graph_2_start_fragment">
        
        <fragment
                android:id="@+id/nav_graph_2_start_fragment"
                android:label="@string/nav_graph_2_start_fragment_label"
                android:name="my.package.ui.NavGraph2StartFragment"
                tools:layout="@layout/fragment_nav_graph_2_start">
        </fragment>
        <!-- In here is where I get the problem -->
    </navigation>
    
</navigation>

解决方法

我的问题如下:

更改配置后,NavGraph返回其起始目的地,但无论如何最后加载的活动片段都将被加载。这意味着实际启动的Fragment和navGraph的当前目标不同步。
当我的Fragment然后尝试加载navGraph范围内的ViewModel时,它失败了,因为navGraph认为它在与实际不同的Fragment上。

要解决我的问题,我必须使用活动saveInstanceState Bundle保存和恢复navController的状态。 (来源:https://stackoverflow.com/a/59987336

override fun onSaveInstanceState(savedInstanceState: Bundle) {
    super.onSaveInstanceState(savedInstanceState)
    savedInstanceState.putBundle("nav_state",fragment.findNavController().saveState())
}

// restore in RestoreInstanceState
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
    super.onRestoreInstanceState(savedInstanceState)
    fragment.findNavController().restoreState(savedInstanceState.getBundle("nav_state"))
}

// or restore in onCreate
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    if (savedInstanceState?.containsKey("nav_state") == true) {
        fragment.findNavController().restoreState(savedInstanceState.getBundle("nav_state"))
    }
}
,

对于来到这里的其他人,我在当前显示对话框时遇到了这个问题,并且我在对话框被关闭之前向使用 by navGraphViewModels() 的 Fragment 发出了 navController.navigate() 调用。

就好像导航库无法理解在显示对话框时有一个具有该 ID 的目的地可用。

为了更清楚,这个对话框是在我的导航图 XML 中使用 <dialog> 属性显示的。

我的修复(目前)是确保在通过 view.postDelayed({ navController.navigate(elsewhere)},300)

进一步调用导航到别处之前关闭对话框

这不是我第一次遇到 NavController 在显示对话框时尝试导航的问题。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...