I've creating a test activity that updates some text in my MyViewModel.
I'd like to observe these changes in a Fragment, but when I use
MyViewModel myViewModel = new ViewModelProvider(this).get(MyViewModel.class);
it gives me a different instance of MyViewModel than that used in the activity, which results in my onChanged()
callback in the fragment not being called.
Only when I modify that same fragment code to
HomeViewModel homeViewModel = new ViewModelProvider(getActivity()).get(HomeViewModel.class);
does the fragment get the same instance of MyViewModel as the activity - so onChanged()
is successfully called.
However, I'm not sure if using getActivity()
as the ViewModelStoreOwner is the proper way of doing things as I haven't seen this in any examples anywhere. I'm wondering if there might be a better ViewModelStoreOwner I should be using in this instance?
To share the objects among fragments, simply use the activity instance for creating ViewModelProvider which will use the same ViewModelStoreOwner in all fragments hence will return the persisted object of viewmodel (if created before).
Use the 'by viewModels()' Kotlin property delegate or ViewModelProvider , passing in the fragment. This function is deprecated. Use the 'by viewModels()' Kotlin property delegate or ViewModelProvider , passing in the activity. of (fragment: Fragment, factory: ViewModelProvider.
Creates ViewModelProvider , which will create ViewModels via the given Factory and retain them in the given store . ViewModelStore : ViewModelStore where ViewModels will be stored.
So, you can think of as wrapper around library class for ViewModelProvider . On the other hand, ViewModelProvider (belongs to Maven artifact android. arch. lifecycle:viewmodel) is class that provides ViewModels for a scope.
I'm wondering if there might be a better ViewModelStoreOwner I should be using in this instance?
You should use activity
instance for sharing the same instance among fragments in the same activity.
Both Activity and Fragment implements their own ViewModelStoreOwner interface and implements the getViewModelStore()
method. getViewModelStore()
provide the ViewModelStore
instance which is used to store the viewmodel
objects, created by the ViewModelProvider
.
Note: ComponentActivity implements the ViewModelStoreOwner
interface and FragmentActivity
(parent of AppCompatActivity) inherits the implementation.
So both Activity and Fragment have specific implementation for the ViewModelStoreOwner
interface methods and store the viewmodel instance as per the lifecycle
of the objects(including the configuration changes).
Since fragments belong to activity get the same activity instance so using the getActivity()
will result in using the ViewModelStoreOwner
object of the activity. To share the objects among fragments, simply use the activity instance for creating ViewModelProvider
which will use the same ViewModelStoreOwner
in all fragments hence will return the persisted object of viewmodel
(if created before).
Having an Activity
which does as little as possible has become a "best practice" for some time now, so the scenario of an Activity
and a Fragment
which need access to the same ViewModel
instance may not be covered by many guides.
But "there is no rule without an exception", and your scenario is similar to the one where an Activity
has two Fragment
s which need to share data.
In this case, one uses the Activity
scope for the ViewModel
to make sure every component will have access to the same instance. See also the section "Share data between fragments" in the View Model Overview at developer.android.com
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With