Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to scope ViewModels properly?

I am trying to wrap my head around the new Android Architecture Components, specifically the ViewModel.

My impression is that a Fragment should not know about what Activity or Fragment it is owned by, so that it can be used in different contexts of the application. The examples seem to contradict this by declaring the ViewModel scope directly in the Fragment, rather than the Fragment owner:

viewModel = ViewModelProviders.of(getActivity()).get(SomeViewModel.class);

I would like to be able to use this Fragment in a Master/Detail configuration, where both share the same state (i.e. ViewModel instance), as well as inside a ViewPager, where all Fragments require separate state (i.e. separate ViewModel instances). I would expect the Fragment owner to dictate the scope, which does not seem to be supported with this approach.

A workaround I came up with could be to optionally pass in a configured ViewModelProvider to explicitly broaden the scope of a ViewModel if necessary (e.g. in the Master/Detail configuration) and have separate ViewModels by default:

final ViewModelProvider viewModelProvider;
if (viewModelProviderOverride != null) {
    viewModelProvider = viewModelProviderOverride;
} else {
    viewModelProvider = ViewModelProviders.of(this);
}

viewModel = viewModelProvider.get(SomeViewModel.class);

This way, the owner can decide whether multiple Fragments will share their state or not. I haven't fully thought this through yet, but it seems kind of fishy, since nothing close to it seems to be hinted at in the docs. I feel like I am missing something obvious.

like image 562
jwueller Avatar asked Aug 20 '17 12:08

jwueller


People also ask

What is the scope of a ViewModel?

A ViewModelScope is defined for each ViewModel in your app. Any coroutine launched in this scope is automatically canceled if the ViewModel is cleared. Coroutines are useful here for when you have work that needs to be done only if the ViewModel is active.

How do you pass data from ViewModel to activity?

Passing Data between fragments in Android using ViewModel: This is because ViewModel is tied to the activity lifecycle. To actually pass the data between fragments, we need to create a ViewModel object with an activity scope of both the fragments, initialize the ViewModel , and set the value of the LiveData object.

How does a ViewModel work internally?

ViewModel class is designed to store and manage UI-related data in a lifecycle conscious way.It is the main component in the MVVM architecture. ViewModel can be created with activity context or fragment context. When a ViewModel object is created, it is stored inside Activity OR FragmentManager.

Is ViewModel Life Cycle Aware?

Lifecycle Awareness: ViewModel objects are also lifecycle-aware. They are automatically cleared when the Lifecycle they are observing gets permanently destroyed.


1 Answers

Saying viewModel = ViewModelProviders.of(getActivity()).get(SomeViewModel.class); means that you would like the state of the ViewModel to be scoped to the Activity. If you would not like the Fragment to be scoped to the activity you can just call viewModel = ViewModelProviders.of(this).get(SomeViewModel.class);. Now all you do is if (shareState) then call the first and if not call the second.

like image 189
HaydenKai Avatar answered Oct 01 '22 10:10

HaydenKai