12

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?

ban-geoengineering
  • 18,324
  • 27
  • 171
  • 253

2 Answers2

6

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).

Pavneet_Singh
  • 36,884
  • 5
  • 53
  • 68
1

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 Fragments 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

Bö macht Blau
  • 12,820
  • 5
  • 40
  • 61