Viewmodel的原理
介绍
google的Jetpack推出的Viewmodel会绑定组件的生命周期,当Activity finish的时候,Viewmodel会执行onCleared()方法释放资源,避免内存泄漏。
使用
1.定义Viewmodel
class ShareViewModel: ViewModel() {
val mutableLiveData:MutableLiveData<String> = MutableLiveData()
}
2.使用
val viewModel = ViewModelProvider(activity as ViewModelStoreOwner)[ShareViewModel::class.java]
viewModel.mutableLiveData.observe(activity as LifecycleOwner, Observer {
textView.text = it
})
源码分析
ViewModelProvider构造
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;
}
andoidx.activity:activity:1.0.0@aar中的ComponentActivity实现了ViewModelStoreOwner接口
andoidx.activity:activity:1.1.0@aar中的ComponentActivity实现了ViewModelStoreOwner接口和HasDefaultViewModelProviderFactory接口
我们分析一个1.0.0的ComponentActivity,那么mFactory 就是NewInstanceFactory实例
我们看一下ComponentActivity的getViewModelStore
public ViewModelStore getViewModelStore() {
...
if (mViewModelStore == null) {
mViewModelStore = new ViewModelStore();
}
}
return mViewModelStore;
}
所以ComponentActivity的mViewModelStore 是ViewModelStore的实例
get方法得到Viewmodel
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;
}
第一步是从mViewModelStore的缓存中根据key查询ViewModel,如果缓存中存在 就直接返回,否则就根据mFactory create一个ViewModel然后存储到mViewModelStore中。
根据前边的分析mFactory 是NewInstanceFactory。
public <T extends ViewModel> T create(@NonNull Class<T> 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);
}
}
这里我们发现Viewmodel是根据Class 反射创建出来的实例。
我们有时候看到一个Activity中多个Fragment使用Viewmodel共享数据,他们都是通过使用的用一个activity创建的ViewModelProvider,那么ViewModelProvider中的mViewModelStore是同一个,即共用一个缓存。