使用 setGraph() 以编程方式设置图表会导致应用程序在进程死亡后无法恢复堆栈 (Jetpack Navigation)

Dev*_*000 5 android android-fragments kotlin android-jetpack-compose android-navigation-graph

我目前所处的情况是,重构整个应用程序以形成一个更有凝聚力的整体可能是不可行的,但当前使用 Jetpack Navigation 的方法正在导致崩溃。

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

图A、
图B、
图C

图形 A 通过app:navGraph在活动布局中设置,如果它仍然是唯一使用的图形,则应用程序可以并将在进程死亡后恢复其状态。

然而,在某些时刻,应用程序通过使用 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
Run Code Online (Sandbox Code Playgroud)

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

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

我想知道我是否错过了可以调解这次崩溃的重要步骤。

Vel*_*alı 6

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

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>
Run Code Online (Sandbox Code Playgroud)

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

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

navController.navigate(NavADirections.actionToNavC())
Run Code Online (Sandbox Code Playgroud)

或者直接(用Java)

navController.navigate(R.id.action_to_nav_c);
Run Code Online (Sandbox Code Playgroud)

最后,您的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>
Run Code Online (Sandbox Code Playgroud)