MVVM模式实现了数据和页面的分离。ViewModel的生命周期需要跟随引用他的activity或者fragment。接下来我们就来看看,ViewModel是如何实现生命周期的伴随的。
先从ViewModel的创建开始看
XXXViewModel viewModel = new ViewModelProvider(fragment).get(XXXViewModel.class)
kotlin扩展函数实现的方式最终也是调用ViewModelProvider的方法实现的,具体细节可以看上篇文章介绍,这里不赘述了
先看下ViewModelProvider的构造方法
public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
: NewInstanceFactory.getInstance());
}
构造方法需要传入一个ViewModelStoreOwner,在androidx包中的Fragment和ComponentActivity都实现了这个接口。这个稍后再看
继续看上面的代码,该构造方法调用了另一个构造方法
public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
mFactory = factory;
mViewModelStore = store;
}
mViewModelStore这个变量来自于ViewModelStoreOwner,接下来以Fragment为例,来看看
public ViewModelStore getViewModelStore() {
if (mFragmentManager == null) {
throw new IllegalStateException("Can't access ViewModels from detached fragment");
}
return mFragmentManager.getViewModelStore(this);
}
这里可以看出,Fragment的ViewModelStore是保存在当前实例下。先记住这个结论,待会还用得着。
接下来看factory参数,fragment也是HasDefaultViewModelProviderFactory的实现类,因此获取factory的实例方法为
public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
if (mFragmentManager == null) {
throw new IllegalStateException("Can't access ViewModels from detached fragment");
}
if (mDefaultFactory == null) {
mDefaultFactory = new SavedStateViewModelFactory(
requireActivity().getApplication(),
this,
getArguments());
}
return mDefaultFactory;
}
这里的factory也是fragment中保存的实例
回到ViewModelProvider的get方法
public <T extends ViewModel> T get(@NonNull Class<T> modelClass) {
String canonicalName = modelClass.getCanonicalName();
if (canonicalName == null) {
throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");
}
return get(DEFAULT_KEY + ":" + canonicalName, 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;
}
这里获取缓存的viewmodel的方法 mViewModelStore.get(key)。这里的mViewModelStore就是fragment中存储的。
讲到这里,其实已经清楚了生命周期的绑定过成了。
在ViewModelProvider获取ViewModel的时候,实际上是从fragment中拿到的,如果fragment中没有的话,就创建一个,将其保存在fragment中。因此,只要拿到的fragment实例为同一个,无论新创建多少个ViewModelProvider的实例,最终获取的ViewModel都是同一个。而因为ViewModel的实例实际上是保存在fragment中,因此,viewmodel也会随fragment的销毁而销毁。