导航图范围内的 ViewModel 不会在菜单导航(抽屉)事件中被清除

Navigation graph scoped ViewModel not get cleaned on menu navigation (Drawer) events

我正在为侧边导航菜单使用导航组件和集成的 DrawerLayout。

我有以下导航结构xml配置:

<navigation 
    android:id="@+id/mobile_navigation"
    app:startDestination="@id/nav_apple">

   <navigation android:id="@+id/nav_apple">
      <fragment
          android:id="@+id/nav_apple_fragment"
          android:name="com.my.AppleFragment"
          tools:layout="...">

      ... other fragments and actions which share ViewModel ...

   </navigation>

   <navigation android:id="@+id/nav_orange">
      <fragment
          android:id="@+id/nav_orange_fragment"
          android:name="com.my.OrangeFragment"
          tools:layout="...">
   </navigation>

</navigation>

菜单 xml 是这样的:

<menu>
    <group>
        <item
            android:id="@id/nav_apple"/>
        <item
            android:id="@id/nav_orange" />
    </group>
</menu>

在 activity 中,我的代码与 android 文档中的代码非常相似 (https://developer.android.com/guide/navigation/navigation-ui):

val navController = findNavController(R.id.nav_host_fragment)
appBarConfiguration = AppBarConfiguration(
    topLevelDestinationIds = setOf(
        R.id.nav_apple,
        R.id.nav_orange
    ),
    drawerLayout = binding.drawerLayout
)
setupActionBarWithNavController(navController, appBarConfiguration)
binding.navView.setupWithNavController(navController)

AppleFragment 和 'nav_apple' 图中的其他片段中,我使用以下代码来使用导航图范围的 ViewModel:

private val model: MyViewModel by navGraphViewModels(R.id.nav_apple)

它允许我共享数据并且工作完美,但是当我使用侧面菜单(抽屉)并导航到另一个目的地并返回时 - ViewModel 数据仍然存在,这是不希望的。

根据文档 Any ViewModel objects created in this way live until the associated NavHost and its ViewModelStore are cleared or until the navigation graph is popped from the back stack.,我认为导航抽屉事件就是这种情况,但看起来我遗漏了什么。

根据 Principles of Navigation,您的图表的起始目的地(并且,如果 startDestination 指向 <navigation> 图表,则它的 startDestination)始终开启返回堆栈。

由于导航图本身保留在返回堆栈中,因此附加到该导航图的状态和 ViewModel 也会保留。

multiple back stacks 即将开展的工作中,每个底部导航项都将拥有自己的返回堆栈,并且在项目之间切换会自动保存当前堆栈,并在您重新选择时将其恢复。因此,您应该期望底部导航项在发布后自动保留其 ViewModel。