【发布时间】:2020-03-01 13:31:31
【问题描述】:
我需要将数据从一个片段传输到另一个片段。现在推荐的方法是使用共享的ViewModel。要在两个片段中获得相同的实例,需要共同的所有者。因为它可以是他们共同的Activity。但是使用这种方法(在 Single Activity 的情况下),ViewModel 实例将存在于整个应用程序中。在片段的经典使用中,可以在父片段中指定ViewModelProvider (this),在子片段中指定ViewModelProvider (getParentFramgent ())。因此,ViewModel 的范围仅限于父片段的生命周期。问题是在使用导航组件时,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()不会在真正的父片段完成时被调用。
【问题讨论】:
-
能否贴出添加子片段的代码
-
@FahadAlotaibi,只需 findNavController().navigate(R.id.start_game_fragment)
-
所以,NavHostFragment 将是父片段,所有片段都将添加为子片段
-
@FahadAlotaibi,是的,这个 NavHostFragment 对所有片段都是通用的。它在活动中被实例化。它会在活动存在时继续存在。
-
@FahadAlotaibi,比如我用一个Fragment,一个ViewModel的方式,当fragment结束时,ViewModel会调用onCleared()
标签: android android-fragments android-viewmodel