How to give same instance of ViewModel to both the Parent and Child fragment
Solution 1
Create your ViewModel
with Activity
scope. Then all Fragment
within that Activity
will get same ViewModel
instance.
Check official ViewModelProviders reference. You can create ViewModel
with both Activity
and Fragment
scope.
ViewModelProvider of (FragmentActivity activity)
Creates a ViewModelProvider, which retains ViewModels while a scope of given Activity is alive. More detailed explanation is in ViewModel.
and
ViewModelProvider of (Fragment fragment)
Creates a ViewModelProvider, which retains ViewModels while a scope of given fragment is alive. More detailed explanation is in ViewModel.
Sample code for creating ViewModel
From Activity:
movieListViewModel = ViewModelProviders.of(this).get(MovieListViewModel.class);
From Fragment:
movieListViewModel = ViewModelProviders.of(getActivity()).get(MovieListViewModel.class);
Solution 2
Using Fragment-ktx we can do as In **ParentFragment**
private val viewModel: DemoViewModel by viewModels()
And
In ChildFragment
private val viewModel: DemoViewModel by viewModels(
ownerProducer = { requireParentFragment() }
)
Doing this we can get same instance of ViewModel in Parent Fragment and ChildFragment
add dependencies in app -> build.gralde
implementation 'androidx.fragment:fragment-ktx:1.1.0
Solution 3
Implement fragment-ktx in your app -> build.gradle:
implementation 'androidx.fragment:fragment-ktx:1.2.5
If you are using Navigation Component (https://developer.android.com/guide/navigation)
In the parentFragment, you can get the viewModel like this:
private val viewModel by viewModels<DemoViewModel>()
And then when you need that viewModel in the childFragment you can get it this way:
private val viewModel by viewModels<DemoViewModel>({requireGrandParentFragment()})
the requireGrandParentFragment() is a custom extension of Fragment:
fun Fragment.requireGrandParentFragment() = this.requireParentFragment().requireParentFragment()
If you are not using Navigation Component
you can access it like this:
private val viewModel by viewModels<DemoViewModel>({requireParentFragment()})
Solution 4
I have got a same problem tried above all solution but not working in my scenario come up with a other solution using requireParentFragment() return NavHostFragment in child fragment solve it by using
private val viewModel: childViewModel by viewModels(
ownerProducer = { requireParentFragment().childFragmentManager.primaryNavigationFragment!! }
)
in Parent Fragmet use this
private val viewModel: MyOrdersVM by viewModels()
Related videos on Youtube
mhtmalpani
Updated on March 31, 2022Comments
-
mhtmalpani about 2 years
There are two Fragments: ParentFragment and ChildFragment.
ChildFragment
has been added to a view of theParentFragment
.Now using
Dagger2
for Android has theParentFragmentModule
with a method:@Provides fun provideViewModel(fragment: ParentFragment, myViewModelFactory: MyViewModelFactory): MyViewModel { return ViewModelProviders.of(fragment, myViewModelFactory).get(MyViewModelImpl::class.java) }
Where MyViewModelFactory, MyViewModel, MyViewModelImpl are simple ViewModel logic created in the app.
And the ChildFragmentModule has the method:
@Provides fun provideViewModel(fragment: ChildFragment, myViewModelFactory: MyViewModelFactory): MyViewModel { return ViewModelProviders.of(fragment, myViewModelFactory).get(MyViewModelImpl::class.java) }
This obviously is creating two separate instances of the
ViewModel
as they receive two different fragment instances.How do we make it return the same instance so that the data can be shared between both the Parent and Child fragments?
I have tried passing the
ParentFragment
instead ofChildFragment
in theChildFragmentModule
, but that leads to Dagger dependancy injection error.-
pskink about 6 years
-
-
mhtmalpani about 6 yearsThank you. This works smooth! Just for the knowledge, the Parent and Child fragment scopes are alive at the same time. How can achieve the same thing without using the Activity?
-
Fazal Hussain almost 6 yearsHow to share movieListViewModel to different module? Is that possible
-
A. Kazarovets over 5 yearsWhat about single activity approach? It won't be good to hold all the shared view models linked to one activity.
-
Zain over 5 yearsjust a modification to avoid NullPointerException movieListViewModel = ViewModelProviders.of(requireActivity()).get(MovieListViewModel.class);
-
Victor Okech over 3 yearsTo add on this is it possible to get the view model for a separate activity to send data to the child fragment of the MainActivity?