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的烧毁而烧毁。 |