android - 使用 setGraph() 以编程方式设置图形会导致应用程序无法在进程终止后恢复堆栈(Jetpack 导航)

标签 android kotlin android-fragments android-jetpack-compose android-navigation-graph

我目前处于这样一种情况,重构整个应用程序以构建一个更具凝聚力的整体可能是不可行的,但当前使用 Jetpack Navigation 的方法会导致崩溃。

该应用程序有多个图表,为了简单起见,我们称它们为:

图 A,
图B,
图C

图表 A 通过 app:navGraph 在 Activity 布局中设置,如果它仍然是唯一使用的图表,应用程序可以并且将在进程终止后恢复它的状态。

然而,在某些时刻,应用程序通过使用 FragmentContainerView 的 navController 并使用提供的新图形 ID 调用 setGraph(graphResId: Int) 以编程方式切换图形。在此之前,也使用手动膨胀图。

设置图形的两种方法都会在进程死亡后第一次重启后导致崩溃,并抛出异常:

 Unable to start activity ComponentInfo{com.appname.dev/com.appname.activity.MainActivity}: java.lang.IllegalStateException: Restoring the Navigation back stack failed: destination com.appname.dev:id/graph_b cannot be found from the current destination null

异常发生在MainActivity onCreate调用super.onCreate()

在我看来,我唯一能想到的解决方案是将其他图表包含在第一个图表中,使用操作导航到其他图表,从而避免切换图表。但是,由于应用程序的制作方式,最终可能会非常耗时。

我想知道我是否遗漏了一个可以调解这次崩溃的重要步骤。

最佳答案

好吧,我找到了一个解决方案,它也不需要对代码进行任何微不足道的更改。

nav_a.xml(或您的情况下的图 A)应如下所示:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/nav_a"
    app:startDestination="@id/mainFragment">

    <action android:id="@+id/action_to_nav_c"
        app:destination="@id/nav_c"/>

    <action android:id="@+id/action_to_nav_b"
        app:destination="@id/nav_b"/>

    <fragment
        android:id="@+id/mainFragment"
        android:name="com.example.fragment.MainFragment"
        android:label="@string/home" />

    <include app:graph="@navigation/nav_c" />
    <include app:graph="@navigation/nav_b" />
</navigation>

请注意,操作 action_to_nav_caction_to_nav_b 不在任何其他标签内。这样您就可以从任何地方导航它们而不会出现任何错误。

要导航到 nav_c(在您的情况下为图 C),您可以在 Kotlin 的主机 Activity 中使用安全参数执行此操作:

navController.navigate(NavADirections.actionToNavC())

或直接(在 Java 中)

navController.navigate(R.id.action_to_nav_c);

最后,您的 nav_c.xml 可能如下所示:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/nav_c"
    app:startDestination="@id/settingsFragment">

    <fragment
        android:id="@+id/settingsFragment"
        android:name="com.example.fragment.SettingsFragment"
        android:label="@string/settings" />
</navigation>

关于android - 使用 setGraph() 以编程方式设置图形会导致应用程序无法在进程终止后恢复堆栈(Jetpack 导航),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68357831/

相关文章:

android - 为什么我的应用程序启动后,WorkManager会多次触发?

android - DialogFragment 在方向更改时使应用程序崩溃

android - 如何从抽屉导航中打开一个新 fragment ?

android - 由于 Android Camera Intent 重新绘制屏幕,​​Espresso 测试失败

android - Kotlin 与 Android : Base classes and Kotlin Android Extensions

java - 有没有办法在 kotlin 中实现多个接口(interface)?

android - 如何将我的 Activity 升级为 Fragments 并避免 ClassCastException?

android - 如何创建执行命令的二维码?

java - 将元素添加到 LinkedHashMap 中的 ArrayList [Android]

java - OpenSuse 13.2 上的 Qt for Android