通过源码解析掌握
- ViewModel的创建过程
- ViewModel的存在哪里
- ViewModel的生命周期
- 为什么Activity旋转屏幕后ViewModel可以恢复数据
ViewModel的创建
通过之前对ViewModel的使用,了解ViewModel的创建是通过 ==ViewModelProvider== 来创建的
MyViewModel myViewModel = new ViewModelProvider(this).get(MyViewModel.class);
//或者直接使用工具类创建
//ViewModelProviders是一个工具类,对ViewModelProvider进行了封装
MyViewModel myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
传递的是class ,说明是通过反射来创建的,那么就从ViewModelProvider入手
[ViewModelProvider.java]
public class ViewModelProvider {
private static final String DEFAULT_KEY =
"androidx.lifecycle.ViewModelProvider.DefaultKey";
public interface Factory {
@NonNull
T create(@NonNull Class modelClass);
}
static class OnRequeryFactory {
void onRequery(@NonNull ViewModel viewModel) {
}
}
abstract static class KeyedFactory extends OnRequeryFactory implements Factory {
@NonNull
public abstract T create(@NonNull String key,
@NonNull Class modelClass);
@NonNull
@Override
public T create(@NonNull Class modelClass) {
throw new UnsupportedOperationException("create(String, Class>) must be called on "
+ "implementaions of KeyedFactory");
}
}
private final Factory mFactory;
private final ViewModelStore mViewModelStore;
//ViewModelStoreOwner就是当前Activity,
public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
: NewInstanceFactory.getInstance());
}
public ViewModelProvider(@NonNull ViewModelStoreOwner owner, @NonNull Factory factory) {
this(owner.getViewModelStore(), factory);
}
public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
mFactory = factory;
mViewModelStore = store;
}
@NonNull
@MainThread
public T get(@NonNull Class 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);
}
@SuppressWarnings("unchecked")
@NonNull
@MainThread
public T get(@NonNull String key, @NonNull Class 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的提供者,ViewModelProvider类有两个属性
//负责创建ViewModel的工厂
private final Factory mFactory;
//负责存储ViewModel的存储器
private final ViewModelStore mViewModelStore;
从构造函数来看,有三个构造函数
public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
: NewInstanceFactory.getInstance());
}
public ViewModelProvider(@NonNull ViewModelStoreOwner owner, @NonNull Factory factory) {
this(owner.getViewModelStore(), factory);
}
public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
mFactory = factory;
mViewModelStore = store;
}
创建一个ViewModelProvider 实例对象,获取创建ViewModel的Factory和ViewModelStore的实例对象,ViewModelStoreOwner表示自己存储ViewModel功能的组件,Activity和Fragment都实现了该接口
public interface ViewModelStoreOwner {
/**
* Returns owned {@link ViewModelStore}
*
* @return a {@code ViewModelStore}
*/
@NonNull
ViewModelStore getViewModelStore();
}
该接口就是获取ViewModelStore
接下来是调用 get(@NonNull Class
public T get(@NonNull Class 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 get(@NonNull String key, @NonNull Class modelClass) {
//从ViewModelStore中获取,如果有则返回,如果没有则通过Factory创建一个实例对象
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.
}
}
//通过Factory创建ViewModel实例对象
if (mFactory instanceof KeyedFactory) {
viewModel = ((KeyedFactory) mFactory).create(key, modelClass);
} else {
viewModel = mFactory.create(modelClass);
}
mViewModelStore.put(key, viewModel);
return (T) viewModel;
}
这个方法主要功能:
- 获取类的标准类名,并拼接上默认的Key
- 从ViewModelStore中查找是否有已创建的ViewModel
- 如果ViewModelStore中没有该ViewModel的实例对象,则通过Factory反射创建一个,并保存到ViewModelStore中
从K—V模式来开,ViewModelStore就是通过HashMap来保存ViewModel的
[ViewModelStore.java]
public class ViewModelStore {
private final HashMap mMap = new HashMap<>();
final void put(String key, ViewModel viewModel) {
ViewModel oldViewModel = mMap.put(key, viewModel);
if (oldViewModel != null) {
oldViewModel.onCleared();
}
}
final ViewModel get(String key) {
return mMap.get(key);
}
Set keys() {
return new HashSet<>(mMap.keySet());
}
/**
* Clears internal storage and notifies ViewModels that they are no longer used.
*/
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.clear();
}
mMap.clear();
}
}
这里很简单了,就是HashMap,在Activity或者Fragment的销毁的时候,将map 清空
具体实现在ComponentActivity类中
[ComponentActivity.java]
public ComponentActivity() {
...
getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_DESTROY) {
//不是屏幕横竖屏切换,则清空Map
if (!isChangingConfigurations()) {
getViewModelStore().clear();
}
}
}
});
...
}
接下来看看Factory
/**
* Simple factory, which calls empty constructor on the give class.
*/
public static class NewInstanceFactory implements Factory {
private static NewInstanceFactory sInstance;
/**
* Retrieve a singleton instance of NewInstanceFactory.
*
* @return A valid {@link NewInstanceFactory}
*/
@NonNull
static NewInstanceFactory getInstance() {
if (sInstance == null) {
sInstance = new NewInstanceFactory();
}
return sInstance;
}
@SuppressWarnings("ClassNewInstance")
@NonNull
@Override
public T create(@NonNull Class modelClass) {
//noinspection TryWithIdenticalCatches
try {
return modelClass.newInstance();
} catch (InstantiationException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
} catch (IllegalAccessException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
}
}
}
/**
* {@link Factory} which may create {@link AndroidViewModel} and
* {@link ViewModel}, which have an empty constructor.
*/
public static class AndroidViewModelFactory extends ViewModelProvider.NewInstanceFactory {
private static AndroidViewModelFactory sInstance;
/**
* Retrieve a singleton instance of AndroidViewModelFactory.
*
* @param application an application to pass in {@link AndroidViewModel}
* @return A valid {@link AndroidViewModelFactory}
*/
@NonNull
public static AndroidViewModelFactory getInstance(@NonNull Application application) {
if (sInstance == null) {
sInstance = new AndroidViewModelFactory(application);
}
return sInstance;
}
private Application mApplication;
/**
* Creates a {@code AndroidViewModelFactory}
*
* @param application an application to pass in {@link AndroidViewModel}
*/
public AndroidViewModelFactory(@NonNull Application application) {
mApplication = application;
}
@NonNull
@Override
public T create(@NonNull Class modelClass) {
// 如果是AndroidViewModel,继承了ViewModel并含有Application
if (AndroidViewModel.class.isAssignableFrom(modelClass)) {
//noinspection TryWithIdenticalCatches
try {
return modelClass.getConstructor(Application.class).newInstance(mApplication);
} catch (NoSuchMethodException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
} catch (IllegalAccessException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
} catch (InstantiationException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
} catch (InvocationTargetException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
}
}
return super.create(modelClass);
}
}
实现了Factory的工厂类也很简单,工厂是一个单例,没有构造函数则通过NewInstanceFactory 反射创建
如果是AndroidViewModel则通过AndroidViewModelFactory创建
再来看一下旋转屏幕后ViewModel是怎么恢复数据的,这块代码当然是在Activity里面了;这个方法就是当屏幕旋转会调用的:
@Override
@Nullable
public final Object onRetainNonConfigurationInstance() {
Object custom = onRetainCustomNonConfigurationInstance();
ViewModelStore viewModelStore = mViewModelStore;
// 若 viewModelStore 为空,则尝试从 getLastNonConfigurationInstance() 中获取,mViewModelStore本身就是Activity的成员变量
if (viewModelStore == null) {
// No one called getViewModelStore(), so see if there was an existing
// ViewModelStore from our last NonConfigurationInstance
//
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
viewModelStore = nc.viewModelStore;
}
}
// 依然为空,说明没有需要缓存的,则返回 null
if (viewModelStore == null && custom == null) {
return null;
}
// 创建 NonConfigurationInstances 对象,并赋值 viewModelStore
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.custom = custom;
nci.viewModelStore = viewModelStore;
return nci;
}
看了上面代码,也就是说Activity 在因配置更改而销毁重建过程中会先调用 onRetainNonConfigurationInstance 保存 viewModelStore 实例。
在重建后可以通过 getLastNonConfigurationInstance 方法获取之前的 viewModelStore 实例。
这里就类似Activity的onSaveInstanceState(Bundle)了。
总结
- ViewModel 实例对象是又ViewModelProvider提供的
- 创建ViewModelProvider实例对象需要一个ViewModelStore和Factory,ViewModelStore由ViewModlestoreOwner提供,Activity和Fragment实现该接口,Activity组件当生命周期事件为ON_DESTORY 并且不是横竖屏切换的时候则清空Map
- ViewModelProvider主要的工作就是从ViewModelStore中查是否该实例对象已保存在map中,如果有则直接返回,如果没有则通过Factory反射创建一个ViewModel并保存在ViewModelStore中
- ViewModelStore在Activity或者Fragment生命周期结束的时候清空掉Map中保存的ViewModel
- 屏幕旋转保存数据的实现就类似我们的onSaveInstanceState的实现。