ViewModel分析
Q群的被迫作业这里就写一写
写在前面
首先在官方文档里面,他表明了我们一般在oncreate()
里初始化,也就是viewmodel
实例化的地方。
ViewModelProvider的初始化:
(VM) ViewModelProviders.of(this)
这是以前的初始化现在这个方法已经被不推荐使用了。
如果你看过之前版本的源码会发现和现在已经有些许不同了。
现在你直接使用new ViewModelProvider(activity)
原本的不推荐使用的方法也被修改了。
//用判断是否有默认的factory
//当然你也可以直接塞入一个factory 如果你的viewmodel需要传入一些参数的话
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);
}
先讲NewInstanceFactory
public static class NewInstanceFactory implements Factory {
private static NewInstanceFactory sInstance;
//获得单例
@NonNull
static NewInstanceFactory getInstance() {
if (sInstance == null) {
sInstance = new NewInstanceFactory();
}
return sInstance;
}
//反射创建 这里因为是默认的就没有穿参
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
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);
}
}
}
这里有个新的类ViewModelStore
ViewModelStore
内部维护了一个 HashMap
,其 key 为 DEFAULT_KEY + ViewModel
的Class
对象底层类规范名称,其 value
为对应 ViewModel
对象。每个 Activity
与 Fragment
都对应着一个 ViewModelStore
,用于存储所需的 ViewModel
。
@NonNull
@Override
public ViewModelStore getViewModelStore() {
if (getApplication() == null) {
throw new IllegalStateException("Your activity is not yet attached to the "
+ "Application instance. You can't request ViewModel before onCreate call.");
}
if (mViewModelStore == null) {
//此处为是否需要回复viewmodel 后面会讲到
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
// Restore the ViewModelStore from NonConfigurationInstances
mViewModelStore = nc.viewModelStore;
}
if (mViewModelStore == null) {
mViewModelStore = new ViewModelStore();
}
}
return mViewModelStore;
}
之后 Activity 中创建与获取 ViewModel
@NonNull
@MainThread
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");
}
//这里就是值钱说的默认的key
return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
}
@NonNull
@MainThread
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
//根据key值从 ViewModelStore 中取对应的 ViewModel
ViewModel viewModel = mViewModelStore.get(key);
//判断Class对象是否是ViewModel的Class类或其子类的对象
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);
}
//再把viewmodel保存金 viewModelStrore
mViewModelStore.put(key, viewModel);
return (T) viewModel;
}
标注自己看 我下面有张WINDOWS画图制作的图讲究下看吧
用activity
举个例子
Viewmodel 状态保存
一张谁都见过的图.jpgActivity
可能被重新创建,哪吗viewmodel
是如何保存的那
一般来说需要恢复数据的部分有两种,一种activity被其他资源优先级卡死了,一种是配置变了activity被干掉重建了。
在上面我们说到过activity
会持有ViewModelStore
,在ComponentActivity
中有一个方法叫onRetainNonConfigurationInstance
在该方法中保存了ViewModel
真正销毁之前ActivityThread
会调用activity
的retainNonConfigurationInstances
——>onRetainNonConfigurationInstance
@Override
@Nullable
public final Object onRetainNonConfigurationInstance() {
Object custom = onRetainCustomNonConfigurationInstance();
ViewModelStore viewModelStore = mViewModelStore;
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;
}
}
if (viewModelStore == null && custom == null) {
return null;
}
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.custom = custom;
nci.viewModelStore = viewModelStore;
return nci;
}
那之前是保存恢复的话记得上面之前的ViewModelStores
吗我标记了.
ViewModel 何时判断是否被移除
上图中很明显的标识在ondestory()
之后会onClear()
//ComponentActivity构造方法中
getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_DESTROY) {
//mChangingConfigurations 这个值用来判断是否真的需要被移除 不是重启有兴趣可以自行阅读源码 我以后再写
if (!isChangingConfigurations()) {
getViewModelStore().clear();
}
}
}
});
/**
* 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();
}
这样被移除了之后就会被回收拉在下次回收,因为GC是不回回收强引用的,所以在官方文档中强调了.
ViewModel
不应持有 View
、Lifecycle
、或其他可能持有 Activity
的 Context
的类的引用。
不过总有人喜欢,他也给里面留了条后路,可以在onclear()
去释放他们,不过官方还是强烈建议使用livedata
来通信