Accessing graph-scoped ViewModel of child NavHostFragment using by navGraphViewModels

南笙酒味 提交于 2019-12-13 03:35:08

问题


I am using the Navigation Component of Android Jetpack (2.2.0-alpha01).

I wish to use a child NavHostFragment nested inside my main NavHostFragment, equipped with its own child nav graph. Please view the following image for context:

The child nav host is defined like this inside the fragment that is at the front of the MainNavHost's stack:

<fragment
        android:id="@+id/childNavHostFragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="false"
        app:navGraph="@navigation/child_graph" />

Inside the fragment that is at the front of the CHILD Nav Host Fragment, I am trying to get a ViewModel scoped to the R.navigation.child_graph by using the following code:

private val childGraphScopedViewModel: ChildGraphScopedViewModel by navGraphViewModels(R.navigation.child_graph) {
    viewModelFactory
}

When accessing the childGraphScopedViewModel, I am getting a crash with the error message:

java.lang.IllegalArgumentException: No NavGraph with ID 2131689472 is on the NavController's back stack.

I believe the lazy init call by navGraphViewModel() is looking for the navgraph inside the mainGraph.

How can I access a child navHostFragment scoped ViewModel? Thank you for your time.


回答1:


You can do that by providing the viewModelStore of child NavController

override fun onViewCreated(
     view: View, 
     savedInstanceState: Bundle?
) {
    super.onViewCreated(view, savedInstanceState)

    val childHostFragment = childFragmentManager
          .findFragmentById(R.id.childNavHostFragment) as NavHostFragment

    val childNavController = childHostFragment.navController

    val childViewModel: ChildGraphScopedViewModel = ViewModelProvider(
         childNavController.getViewModelStoreOwner(R.navigation.child_graph)
    ).get(ChildGraphScopedViewModel::class.java)
}

I wrote a Kotlin Extension for making it easier

inline fun <reified T: ViewModel> NavController.viewModel(@NavigationRes navGraphId: Int): T {
    val storeOwner = getViewModelStoreOwner(navGraphId)
    return ViewModelProvider(storeOwner)[T::class.java]
}

Usage

val viewModel = findNavController().viewModel(R.navigation.nav)


来源:https://stackoverflow.com/questions/57741008/accessing-graph-scoped-viewmodel-of-child-navhostfragment-using-by-navgraphviewm

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!