问题
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.
回答1:
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.
来源:https://stackoverflow.com/questions/45993990/how-to-scope-viewmodels-properly