通常是在系统首次调用 Activity 对象的 onCreate()
时请求ViewModel
。ViewModel
存在的时间范围是从首次请求ViewModel
直到 Activity 完成并销毁。
源码分析
在分析源码前,我先提出两个问题,ViewModel 是如何做到让数据可在发生屏幕旋转等配置更改后继续留存(也就是说ViewModel 实例依然存在)?Fragment 之间是如何通过 ViewModel 共享数据的?
先来看看ViewModel
类
public abstract class ViewModel {
···
private volatile boolean mCleared = false;
/**
-
This method will be called when this ViewModel is no longer used and will be destroyed.
-
-
It is useful when ViewModel observes some data and you need to clear this subscription to
-
prevent a leak of this ViewModel.
*/
//该方法将会在 ViewModel 被清除时调用,可以在这个方法里做一些取消注册,防止内存泄漏
@SuppressWarnings(“WeakerAccess”)
protected void onCleared() {
}
@MainThread
final void clear() {
mCleared = true;
···
onCleared();
}
···
}
ViewModel 只是一个抽象类,clear()
方法会在 ViewModel 被清除时调用有,用户可以通过重写 onCleared()
方法来处理一些额外的操作。
再从调用处开始分析
val accountViewModel = ViewModelProvider(this).get(AccountViewModel::class.java)
我们再来看看ViewModelProvider
这个类:
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;
}
最终调用到的构造器都是第三个构造器,再来看看ViewModelStore
和Factory
是什么,因为我们传入的是 Activity(是ViewModelStoreOwner
和HasDefaultViewModelProviderFactory
的实现者),所以才会有owner.getViewModelStore()
,第二个参数是getDefaultViewModelProviderFactory()
。
ViewModelStoreOwner
可以理解为 ViewModelStore(ViewModel 存储器)的拥有者,也就是说我们的 Activity/Fragment 是 ViewModel 存储器的拥有者。
然后我们来看看看ViewModelStore
是什么?
// 存储 ViewModel
public class ViewModelStore {
private final HashMap<String, ViewModel> 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();
}
}
可以看到ViewModelStore
的代码很简单,就是用一个 HashMap 存储了key(String)
和value(ViewModel)
,这里的 key 的名字为
// key 的名字
DEFAULT_KEY + “:” + canonicalName
private static final String DEFAULT_KEY =
“androidx.lifecycle.ViewModelProvider.DefaultKey”;
String canonicalName = modelClass.getCanonicalName();
因为第二个参数是通过getDefaultViewModelProviderFactory()
获取到的,前面说过Activity
是 HasDefaultViewModelProviderFactory
的实现类,我们再来看看Activity
中的getDefaultViewModelProviderFactory()
方法
@NonNull
@Override
public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
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 (mDefaultFactory == null) {
mDefaultFactory = new SavedStateViewModelFactory(
getApplication(),
this,
getIntent() != null ? getIntent().getExtras() : null);
}
return mDefaultFactory;
}
可以看到是通过一个SavedStateViewModelFactory
来获取ViewModelProvider.Factory
,命名也很清晰直观