由 navGraphViewModels 创建 java.lang.IllegalArgumentException:ID 为 <destination id> 的目的地不在 NavController 的返回堆栈中
by navGraphViewModels creates java.lang.IllegalArgumentException: No destination with ID <destination id> is on the NavController's back stack
当发生配置更改并因此重新创建我的 Activity 和 Fragment 时,我的导航图范围的 ViewModel 不可用,而 Fragment 已经重新创建。
似乎在 navGraph 之前重新创建了 Fragment。
我正在使用此代码从我的片段初始化我的 navGraph 范围的 ViewModel:
private val myViewModel: MyViewModel by navGraphViewModels(R.id.nav_graph_id)
如果我尝试在 Fragments onViewCreated
函数中使用 myViewModel
,我会在配置更改后得到 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.
编辑 1:
这是我的 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 无论如何都会加载。这意味着实际启动的 Fragment 和 navGraph 的当前目的地不同步。
当我的 Fragment 然后尝试加载 navGraph 范围的 ViewModel 时,它失败了,因为 navGraph 认为它在不同的 Fragment 上,但实际上是。
为了解决我的问题,我必须使用活动 savedInstanceState Bundle
来保存和恢复 navController 的状态。 (来源:)
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()
的片段发出了 navController.navigate() 调用。
就好像导航库无法理解在显示对话框时存在具有该 ID 的可用目的地。
为了更清楚起见,在我的导航图中使用 <dialog>
属性显示此对话框 XML。
我的解决方法(目前)是确保在通过 view.postDelayed({ navController.navigate(elsewhere)}, 300)
进一步调用导航到其他地方之前关闭对话框
这不是我第一次遇到 NavController 在显示对话框时尝试导航的问题。
改变这个很容易解决:
private val myViewModel: MyViewModel by hiltNavGraphViewModels(R.id.nav_graph_id)
收件人:
private val viewModel: AuthViewModel by activityViewModels{ defaultViewModelProviderFactory }
当发生配置更改并因此重新创建我的 Activity 和 Fragment 时,我的导航图范围的 ViewModel 不可用,而 Fragment 已经重新创建。
似乎在 navGraph 之前重新创建了 Fragment。
我正在使用此代码从我的片段初始化我的 navGraph 范围的 ViewModel:
private val myViewModel: MyViewModel by navGraphViewModels(R.id.nav_graph_id)
如果我尝试在 Fragments onViewCreated
函数中使用 myViewModel
,我会在配置更改后得到 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.
编辑 1:
这是我的 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 无论如何都会加载。这意味着实际启动的 Fragment 和 navGraph 的当前目的地不同步。
当我的 Fragment 然后尝试加载 navGraph 范围的 ViewModel 时,它失败了,因为 navGraph 认为它在不同的 Fragment 上,但实际上是。
为了解决我的问题,我必须使用活动 savedInstanceState Bundle
来保存和恢复 navController 的状态。 (来源:
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()
的片段发出了 navController.navigate() 调用。
就好像导航库无法理解在显示对话框时存在具有该 ID 的可用目的地。
为了更清楚起见,在我的导航图中使用 <dialog>
属性显示此对话框 XML。
我的解决方法(目前)是确保在通过 view.postDelayed({ navController.navigate(elsewhere)}, 300)
这不是我第一次遇到 NavController 在显示对话框时尝试导航的问题。
改变这个很容易解决:
private val myViewModel: MyViewModel by hiltNavGraphViewModels(R.id.nav_graph_id)
收件人:
private val viewModel: AuthViewModel by activityViewModels{ defaultViewModelProviderFactory }