现在viewmodel的实现在androidX前后有两个版本,实现方式有着不小的差异
AndroidX前 viewmodel
使用方法
ViewModelProviders.of(activity/fragment).get(MyViewModel::class.java)
ViewModelProviders
@MainThread
public static ViewModelProvider of(@NonNull Fragment fragment, @Nullable Factory factory) {
Application application = checkApplication(checkActivity(fragment));
if (factory == null) {
factory = AndroidViewModelFactory.getInstance(application);
}
return new ViewModelProvider(ViewModelStores.of(fragment), (Factory)factory);
}
这个方法是为了获取ViewModelProvider
,获取它的参数之一为ViewModelStores.of(activity/fragment)
@MainThread
public static ViewModelStore of(@NonNull FragmentActivity activity) {
return activity instanceof ViewModelStoreOwner ? ((ViewModelStoreOwner)activity).getViewModelStore() : HolderFragment.holderFragmentFor(activity).getViewModelStore();
}
@NonNull
@MainThread
public static ViewModelStore of(@NonNull Fragment fragment) {
return fragment instanceof ViewModelStoreOwner ? ((ViewModelStoreOwner)fragment).getViewModelStore() : HolderFragment.holderFragmentFor(fragment).getViewModelStore();
}
ViewModelStore
public class ViewModelStore {
private final HashMap<String, ViewModel> mMap = new HashMap();
public ViewModelStore() {
}
final void put(String key, ViewModel viewModel) {
ViewModel oldViewModel = (ViewModel)this.mMap.put(key, viewModel);
if (oldViewModel != null) {
oldViewModel.onCleared();
}
}
final ViewModel get(String key) {
return (ViewModel)this.mMap.get(key);
}
public final void clear() {
Iterator var1 = this.mMap.values().iterator();
while(var1.hasNext()) {
ViewModel vm = (ViewModel)var1.next();
vm.onCleared();
}
this.mMap.clear();
}
}
viewModel 就是存储在ViweModelStore中的
获取viewmodelStore:如果activity/fragment实现了ViewModelStoreOwner那就是它们自己管理了ViewModelStore
,如果没有实现就会创建一个HolerFragment来管理viewmodelStore
HolderFragment
HolderFragment holderFragmentFor(FragmentActivity activity) {
FragmentManager fm = activity.getSupportFragmentManager();
HolderFragment holder = findHolderFragment(fm);
if (holder != null) {
return holder;
} else {
holder = (HolderFragment)this.mNotCommittedActivityHolders.get(activity);
if (holder != null) {
return holder;
} else {
if (!this.mActivityCallbacksIsAdded) {
this.mActivityCallbacksIsAdded = true;
activity.getApplication().registerActivityLifecycleCallbacks(this.mActivityCallbacks);
}
holder = createHolderFragment(fm);
this.mNotCommittedActivityHolders.put(activity, holder);
return holder;
}
}
}
HolderFragment holderFragmentFor(Fragment parentFragment) {
FragmentManager fm = parentFragment.getChildFragmentManager();
HolderFragment holder = findHolderFragment(fm);
if (holder != null) {
return holder;
} else {
holder = (HolderFragment)this.mNotCommittedFragmentHolders.get(parentFragment);
if (holder != null) {
return holder;
} else {
parentFragment.getFragmentManager().registerFragmentLifecycleCallbacks(this.mParentDestroyedCallback, false);
holder = createHolderFragment(fm);
this.mNotCommittedFragmentHolders.put(parentFragment, holder);
return holder;
}
}
}
这两个方法就是为了获取或者创建HolderFragment
public HolderFragment() {
this.setRetainInstance(true);
}
添加 setRetainInstance 为 true 那么在activity销毁重建是 fragment 不会走destory方法。里面的viewModelstore就保存下来了。
AndroidX 之后
使用方法
val viewModel = ViewModelProvider(this).get(DemoViewModel::class.java)
现在已经没有HolderFragment 了,ComponentActivity 和 Framgnet 已经自己实现了viewModelStoreOwner
, 但是viewmodelStore的代码并没有任何变化。所以只要看viewmodelstore如何保存的就行了。
找到getViewModelStore
-> ensureViewModelStore
void ensureViewModelStore() {
if (mViewModelStore == null) {
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
// Restore the ViewModelStore from NonConfigurationInstances
mViewModelStore = nc.viewModelStore;
}
if (mViewModelStore == null) {
mViewModelStore = new ViewModelStore();
}
}
}
这里是确保viewmodelstore不为null,那肯定之前就有为viewmodelstore赋值的地方了。
onRetainNonConfigurationInstance()
public final Object onRetainNonConfigurationInstance() {
// Maintain backward compatibility.
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;
// 把viewModelStore放到NonConfigurationInstances中并返回,这样当页面被重建而销毁时ViewModelStore就被保存起来了
nci.viewModelStore = viewModelStore;
return nci;
}
在Activity启动流程中,当ActivityThread执行performDestroyActivity这个方法时,会调用Activity的retainNonConfigurationInstances()方法获取到保存的数据并保存到ActivityClientRecord中。
//Activity中的retainNonConfigurationInstances()方法
NonConfigurationInstances retainNonConfigurationInstances() {
//ComponentActivity中的onRetainNonConfigurationInstance()方法
Object activity = onRetainNonConfigurationInstance();
···
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.activity = activity;
···
return nci;
}
ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing, int configChanges, boolean getNonConfigInstance, String reason) {
...
//保存retainNonConfigurationInstances中的数据到ActivityClientRecord中
ActivityClientRecord r = mActivities.get(token);
r.lastNonConfigurationInstances = r.activity.retainNonConfigurationInstances();
...
return r;
当页面重建完成,ActivityThread执行了performLaunchActivity方法时,会调用Activity的attach方法,便会把刚刚存储的数据,传递进去。
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
//传递之前储存的数据
activity.attach(......, r.lastNonConfigurationInstances,.....);
}