使用导航组件时从子对象获取父片段

问题描述 投票:0回答:1

我需要将数据从一个片段传输到另一个片段。现在,推荐的方法是使用共享的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()

android android-fragments android-viewmodel
1个回答
0
投票
这里是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()中。

© www.soinside.com 2019 - 2024. All rights reserved.