Мне нужно перенести данные из одного фрагмента в другой. Теперь рекомендуемый способ сделать это - использовать общий ViewModel
. Чтобы получить один и тот же экземпляр в обоих фрагментах, нужен общий владелец. Как это может быть их общее Activity
. Но при таком подходе (в случае Single Activity) экземпляр ViewModel
будет существовать во всем приложении. В классе c использование фрагментов вы можете указать ViewModelProvider (this)
в родительском фрагменте и ViewModelProvider (getParentFramgent ())
в дочернем. Таким образом, область действия ViewModel
ограничена сроком жизни родительского фрагмента. Проблема в том, что при использовании компонента навигации getParentFramgent ()
вернет NavHostFragment, а не родительский фрагмент. Что мне нужно сделать?
Примеры кода :
Где-то в навигационной_графе. 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()
не будет вызвано, когда закончится реальный родительский фрагмент.