android - 使用导航组件时从子级获取父级 fragment

标签 android android-fragments android-viewmodel

我需要将数据从一个 fragment 传输到另一个 fragment 。现在推荐的方法是使用共享 ViewModel .要在两个 fragment 中获得相同的实例,需要共同的所有者。因为它可以是他们共同的Activity .但是使用这种方法(在单 Activity 的情况下),ViewModel实例将存在于整个应用程序中。在 fragment 的经典使用中,可以指定ViewModelProvider (this)在父 fragment 中,和 ViewModelProvider (getParentFramgent ())在 child 。因此,ViewModel 的范围仅限于父 fragment 的生命周期。问题是在使用导航组件时,getParentFramgent ()将返回 NavHostFragment,而不是父 fragment 。我需要做什么?

代码示例 :

在 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() 返回)作为所有 fragment 的共同点,但随后与 Activity 的情况一样, ViewModel.onCleared()当真正的父 fragment 完成时不会被调用。

最佳答案

真的没有办法做到这一点。

这是来自 androidx.navigation.fragment.FragmentNavigator 的代码 fragment :

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() .因此,子 fragment 没有被添加,而是被一个新的替换,所以它不会在getParentFramgent()中。 .

关于android - 使用导航组件时从子级获取父级 fragment ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60475611/

相关文章:

android - 从 App 的 Android 部分调用 Flutter 函数

android - 查找用户位置

android - 撰写创建新的 ViewModel 实例

android - View 模型无法观察到更改

android - performAction() 中的 SCROLL_TO_POSITION 返回 false AccessibilityService Android

java - TextView 设置可见性不起作用

Android PopupWindow 与 DialogFragment

android - 当 Activity 在其进程被杀死后重新创建时, fragment 后台是否也恢复了?

java - 需要有关抽屉导航过渡的帮助

android - 为AndroidViewModel创建ViewModelFactory的正确方法是什么