Table of contents
We use the life cycle of ViewModel as the main line to explain the relationship between ViewModel, ViewModelProvider and ComponentActivity.
1. The birth of ViewModel
Create ViewModel by calling the get method of ViewModelProvider.
mainViewModel = ViewModelProvider(this).get(MainViewModel::class.java)
//ViewModelProvider.class
public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
: NewInstanceFactory.getInstance());
}
public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
mFactory = factory;
mViewModelStore = store;
}
public ViewModelStore getViewModelStore() {
...
ensureViewModelStore();
return mViewModelStore;
}
void ensureViewModelStore() {
if (mViewModelStore == null) {
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
// Restore the ViewModelStore from NonConfigurationInstances
mViewModelStore = nc.viewModelStore;
}
if (mViewModelStore == null) {
mViewModelStore = new ViewModelStore();
}
}
}
Get the owner's ViewModelStore (AppCompatActivity compatible -> FragmentActivity -> ComponentActivity component ComponentActivty implements the ViewModelStoreOwner and LifecycleOwner interfaces)
There is a HashMap inside ViewModelStore to store ViewModel
So mViewModelStore in ViewModelStore is Activity, ViewModelProvider holds a reference to mViewModelStore, and ViewModelProvider internally holds a reference to mViewModelStore
//ViewModelProvider.class
public <T extends ViewModel> T get(@NonNull Class<T> modelClass) {
...
return get(DEFAULT_KEY + ":" + modelClass.getCanonicalName(), modelClass);
}
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
ViewModel viewModel = mViewModelStore.get(key);
if (modelClass.isInstance(viewModel)) {
if (mFactory instanceof OnRequeryFactory) {
((OnRequeryFactory) mFactory).onRequery(viewModel);
}
return (T) viewModel;
} else {
//noinspection StatementWithEmptyBody
if (viewModel != null) {
// TODO: log a warning.
}
}
if (mFactory instanceof KeyedFactory) {
viewModel = ((KeyedFactory) mFactory).create(key, modelClass);
} else {
viewModel = mFactory.create(modelClass);
}
mViewModelStore.put(key, viewModel);
return (T) viewModel;
}
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
return modelClass.newInstance();
...
}
The get method will create a ViewModel object, using the Factory factory to create it, and the factory creates the ViewModel through reflection.
And because we use ViewModelProvider (ViewModelStoreOwner) to create ViewModelProvider, the ViewModelProvider.Factory used here is actually ComponentActivity, because ComponentActivity implements the HasDefaultViewModelProviderFactory interface.
public class ComponentActivity extends androidx.core.app.ComponentActivity implements
...
HasDefaultViewModelProviderFactory{
public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
...
mDefaultFactory = new SavedStateViewModelFactory(
getApplication(),
this,
getIntent() != null ? getIntent().getExtras() : null);
return mDefaultFactory;
}
}
So far, the ViewModel we created is actually saved in the HashMap of mViewModelStore, and mViewModelStore is a member variable belonging to Activity.
2. The end of ViewModel
Start: The creation of ViewModel has been said a lot above, the beginning of life is from the creation of ViewModel
End: The end of life is not controlled by ourselves, because our ViewModel is stored in the ViewModelStore of Activity, so the end of life is also handled by Activity.
public ComponentActivity() {
Lifecycle lifecycle = getLifecycle();
...
getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_DESTROY) {
...
getViewModelStore().clear();
}
}
});
...
}
When creating ComponentActivity, we registered the Lifecycle listener of Activity. When Activity.onDestory, all ViewModels will be cleared automatically, and an onCleared callback will be given to ViewModel, telling it that no one has referenced it. and to
The mBagOfTags in the ViewModel call the close method one by one
//ViewModel.class
protected void onCleared() {
}
@MainThread
final void clear() {
mCleared = true;
if (mBagOfTags != null) {
synchronized (mBagOfTags) {
for (Object value : mBagOfTags.values()) {
// see comment for the similar call in setTagIfAbsent
closeWithRuntimeException(value);
}
}
}
onCleared();
}
To sum up, ViewModel has a life cycle, and the end of life is controlled by Activity
3. Summary:
1. ViewModelProvider is actually just an intermediary:
The creation of ViewModel, the factory ViewModelProvider.Factory is actually held by ComponentActivity.
For the storage of ViewModel, ViewModelStore is responsible and held by ComponentActivity.
The destruction of ViewModel is still in charge of ComponentActivity.
2. ViewModel is the core VM in MVVM, and ComponentActivity is responsible for the life cycle and storage.
3. ComponentActivity is the sole steward of ViewModel.
4. The view layer in MVVM is referenced by the viewmodel layer.