我需要将数据从一个片段传输到另一个片段。现在,推荐的方法是使用共享的ViewModel
。为了在两个片段中获得相同的实例,需要公共所有者。由于可能是它们的共同点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()
。
androidx.navigation.fragment.FragmentNavigator
中的代码段:public NavDestination navigate(@NonNull Destination destination, @Nullable Bundle args,
@Nullable NavOptions navOptions, @Nullable Navigator.Extras navigatorExtras) {
// ...
final FragmentTransaction ft = mFragmentManager.beginTransaction();
// ...
ft.replace(mContainerId, frag);
ft.setPrimaryNavigationFragment(frag);
// ...
}
在引擎盖下,使用FragmentManager
,其称为replace()
。因此,不会添加子片段,而是将其替换为新的子片段,因此它将不会出现在getParentFramgent()
中。
• 从对象数组内部的数组中获取特定对象 express js mongodb
• 在运行时获取 Jetpack Compose 组件层次结构?
• 在 django 组件中使用类继承时重复加载媒体(CSS,JS)
• Angular Material:如何从子组件导航到不同的 mat-tab 组件?
• PHP - 如何有效地识别和计算非常大的 XML 的父元素
• 如何在聚合的投影阶段将元素的子集从一个数组添加到另一个数组
• Map 在使用 react-leaflet 初始化时不可见
• 在 onInit 和 afterViewInit 期间返回未定义的 Angular JSON 数据(错误类型错误)
• 用componentDidUpdate()和React-APlayer库更新状态。
• 使用片段时如何从主 Activity 类的资源文件中获取值?