我需要将数据从一个片段传递到另一个片段。现在推荐的方法是使用共享
在 navigation_graph.xml 中的某个位置:
ViewModel
。为了在两个片段中都能使用相同的实例,需要一个公共所有者。这可以是它们的共同 Activity
。但是使用这种方法时(在单个 Activity 的情况下),ViewModel
实例将在整个应用程序中存在。在经典的片段用法中,您可以在父片段中指定 ViewModelProvider (this)
,并在子片段中指定 ViewModelProvider (getParentFramgent ())
。因此,ViewModel
的范围仅限于父片段的生命周期。问题是,当使用 Navigation 组件时,getParentFramgent ()
将返回 NavHostFragment,而不是父片段。我该怎么办?
示例代码:在 navigation_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/nav"
app:startDestination="@id/mainMenuFragment">
<fragment
android:id="@+id/mainMenuFragment"
android:name="com.mypackage.mainmenu.MainMenuFragment"
android:label="MainMenu"
tools:layout="@layout/fragment_main_menu">
<action
android:id="@+id/start_game_fragment"
app:destination="@id/gameNav" />
</fragment>
<navigation
android:id="@+id/gameNav"
app:startDestination="@id/gameFragment">
<fragment
android:id="@+id/gameFragment"
android:name="com.mypackage.game.GameFragment"
android:label="@string/app_name"
tools:layout="@layout/fragment_game"/>
</navigation>
</navigation>
在MainMenuFragment
的某个地方:
override fun startGame(gameSession: GameSession) {
//This approach doesn't work
ViewModelProvider(this)[GameSessionViewModel::class.java].setGameSession(
gameSession
)
findNavController().navigate(R.id.start_game_fragment)
}
GameFragment
:
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
gameSessionViewModel =
ViewModelProvider(requireParentFragment())[GameSessionViewModel::class.java].apply {
val session = gameSession.value
)
}
}
编辑:
我可以使用NavHostFragment
(从getParentFragment()
返回)作为所有片段的公共部分,但是,与Activity
一样,在真正的父片段完成时将不会调用ViewModel.onCleared()
。