ViewModelStore
存储ViewModel的数据类 ,内部是一个HashMap
`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.
* 在Activity销毁时会调用
*/
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.clear();
}
mMap.clear();
}
在Activity的构造方法中,会去拿到lifecycle, 通过观察lifecycle的生命周期,如果是on_Destroy
会调用viewmodelStrore的clear(),然后会去调用所有viewmodel的onCLear()
getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_DESTROY) {
// Clear out the available context
mContextAwareHelper.clearAvailableContext();
// And clear the ViewModelStore
if (!isChangingConfigurations()) { //后面分析
getViewModelStore().clear();
}
}
}
});
###ViewModelProviders.Factory
ViewModelProviders的内部类,只有一个create方法,用于创建ViewModel
public interface Factory {
/**
* Creates a new instance of the given {@code Class}.
*
*
* @param modelClass a {@code Class} whose instance is requested
* @param The type parameter for the ViewModel.
* @return a newly created ViewModel
*/
@NonNull
T create(@NonNull Class modelClass);
}
ViewModelProviders.of(this, new ViewModelFactory<>()).get(ViewModel.class)
从of(this, factary)
这句往下看:
public static ViewModelProvider of(@NonNull FragmentActivity activity,
@Nullable Factory factory) {
Application application = checkApplication(activity);
if (factory == null) { //若factory为空 创建一个默认的factory
factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);
}
//创建ViewModelProvider返回,将activity的viewModelStaore,以及factory当作变量存储
return new ViewModelProvider(activity.getViewModelStore(), factory);
}
get(ViewModel.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");
}
//DEFAULT_KEY + ":" + canonicalName, modelClass为存储viewmodel的key
return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
}
public T get(@NonNull String key, @NonNull Class modelClass) {
ViewModel viewModel = mViewModelStore.get(key); //从map中获取viewModel
if (modelClass.isInstance(viewModel)) { //map中存在且为modelClass类型 则返回
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); //通过factory创建viewmodel
}
mViewModelStore.put(key, viewModel); //存储
return (T) viewModel;
}
以上就是ViewModel基本工作流程
在Activity重建时可保存数据
在创建ViewModelProvider时,会通过Activty拿到ViewModelStore,通过ViewModelStore获取ViewModel
new ViewModelProvider(activity.getViewModelStore(), factory)
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.");
}
ensureViewModelStore();
return mViewModelStore;
}
void ensureViewModelStore() {
if (mViewModelStore == null) {
//获取最近一次Activity重建时保存下来的数据
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
// Restore the ViewModelStore from NonConfigurationInstances
mViewModelStore = nc.viewModelStore;
}
if (mViewModelStore == null) {
mViewModelStore = new ViewModelStore();
}
}
}
大家都知道Activty横竖屏切换时会触发onSaveInstanceState,而还原时会触发onRestoreInstanceState
,但是Android的Activity类还有一个方法名为onRetainNonConfigurationInstance和getLastNonConfigurationInstance这两个方法
在恢复窗口时,我们可以不使用 onRestoreInstanceState,而代替的是getLastNonConfigurationInstance
public Object getLastNonConfigurationInstance() {
return mLastNonConfigurationInstances != null
? mLastNonConfigurationInstances.activity : null;
}
mLastNonConfigurationInstances
在Activity attach阶段被赋值,分析Activity的生命周期具体调用时机,我们知道Activity是通过反射创建出来的,之后会执行attach方法,所以我猜测mLastNonConfigurationInstances是通过AMS传递过来,那么它是在哪里保存的呢?
在Activity configuration发生改变时,将伴随onDestroy被系统调用 ,onRetainNonConfigurationInstance也会被调用
public final Object onRetainNonConfigurationInstance() {
// Maintain backward compatibility.
Object custom = onRetainCustomNonConfigurationInstance();
ViewModelStore viewModelStore = mViewModelStore;
if (viewModelStore == null) {
//获取最近一次Activity重建时保存下来的数据
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;
}
通过上述一系列操作保存Activity的ViewMdoel,也就实现了ViewModel的数据保存。
2、实现Activity与Fragment数据共享
Fragment依附在Activity之上,所以在创建Viewmdoel时可以传入当前的Actiivty,这时就会传回一个Activity已经创建好的ViewModel,这样就可以方便的访问到这个ViewModel上的数据,在Activity 修改数据后Fagment也可以拿到
public class MyFragment extends Fragment {
public void onStart() {
//这里拿到的ViewModel实例,其实是和Activity中创建的是一个实例
UserModel userModel = ViewModelProviders.of(getActivity()).get(UserModel.class);
}
}
3、实现Fragemnt与Fragment之间数据共享
多个Fragment之间可通过Activity获取到同一个ViewModel,当在同一个Viewmodel中通过liveData更新数据
那么多个Fragment都可以收到。