Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to give same instance of ViewModel to both the Parent and Child fragment

There are two Fragments: ParentFragment and ChildFragment. ChildFragment has been added to a view of the ParentFragment.

Now using Dagger2 for Android has the ParentFragmentModule 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 of ChildFragment in the ChildFragmentModule, but that leads to Dagger dependancy injection error.

like image 569
mhtmalpani Avatar asked May 26 '18 06:05

mhtmalpani


2 Answers

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);
like image 62
Abu Yousuf Avatar answered Oct 06 '22 01:10

Abu Yousuf


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
like image 20
Alok Mishra Avatar answered Oct 05 '22 23:10

Alok Mishra