版本:
androidx.appcompat:appcompat:1.0.2
androidx.lifecycle:lifecycle-extensions:2.0.0
ViewModel的基本使用方式是ViewModelProviders.of(this).get(viewModelClass),就按照该使用流程捋一捋源码
ViewModelProviders.java
@NonNull
@MainThread
public static ViewModelProvider of(@NonNull FragmentActivity activity) {
return of(activity, null);
}
@NonNull
@MainThread
public static ViewModelProvider of(@NonNull FragmentActivity activity,
@Nullable Factory factory) {
//检查application是否为null
Application application = checkApplication(activity);
if (factory == null) {
//默认创建一个ViewModelFactory
factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);
}
//activity.getViewModelStore()东西有点多,放到最后捋,先看ViewModelProvider的get方法
return new ViewModelProvider(activity.getViewModelStore(), factory);
}
ViewModelProvider.java
public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
mFactory = factory;
this.mViewModelStore = store;
}
public static class AndroidViewModelFactory extends ViewModelProvider.NewInstanceFactory {
private static AndroidViewModelFactory sInstance;
@NonNull
public static AndroidViewModelFactory getInstance(@NonNull Application application) {
if (sInstance == null) {
sInstance = new AndroidViewModelFactory(application);
}
return sInstance;
}
private Application mApplication;
public AndroidViewModelFactory(@NonNull Application application) {
mApplication = application;
}
@NonNull
@Override
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
if (AndroidViewModel.class.isAssignableFrom(modelClass)) {
try {
//其实是通过反射的方式创建一个ViewModel
return modelClass.getConstructor(Application.class).newInstance(mApplication);
} catch (NoSuchMethodException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
} catch (IllegalAccessException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
} catch (InstantiationException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
} catch (InvocationTargetException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
}
}
return super.create(modelClass);
}
}
@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");
}
return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
}
@NonNull
@MainThread
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
//ViewModelStore内部其实就是存了一个map而已,value为ViewModel
//如果获取到直接返回ViewModel,没有就创建一个然后存入到ViewModelStore
//所以,只要ViewModel不被清空,那么对应的ViewModel也不会被重置
ViewModel viewModel = mViewModelStore.get(key);
if (modelClass.isInstance(viewModel)) {
return (T) viewModel;
} else {
if (viewModel != null) {
// TODO: log a warning.
}
}
viewModel = mFactory.create(modelClass);
mViewModelStore.put(key, viewModel);
return (T) viewModel;
}
接下来看一下activity.getViewModelStore(),看看ViewModel是如何在屏幕旋转等操作后活下来的
FragmentActivity.java - getViewModelStore
static final class NonConfigurationInstances {
Object custom;
ViewModelStore viewModelStore;
FragmentManagerNonConfig fragments;
}
@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) {
//若ViewModelStore未null
//获取NonConfigurationInstances
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
//判断NonConfigurationInstances是否为null来决定是否需要新建一个ViewModelStore
if (nc != null) {
// 从NonConfigurationInstances内恢复ViewModelStore
//所以可以看看NonConfigurationInstances是如何被保存下来的
mViewModelStore = nc.viewModelStore;
}
if (mViewModelStore == null) {
mViewModelStore = new ViewModelStore();
}
}
return mViewModelStore;
}
getViewModelStore主要的操作就在getLastNonConfigurationInstance()内
Activity.java - getLastNonConfigurationInstance
public Object getLastNonConfigurationInstance() {
//mLastNonConfigurationInstances不为null获取NonConfigurationInstances内的activity
//mLastNonConfigurationInstances的赋值在该java文件内的attach方法内
//performLaunchActivity最终会调用到attach
return mLastNonConfigurationInstances != null
? mLastNonConfigurationInstances.activity : null;
}
static final class NonConfigurationInstances {
Object activity;
HashMap<String, Object> children;
FragmentManagerNonConfig fragments;
ArrayMap<String, LoaderManager> loaders;
VoiceInteractor voiceInteractor;
}
下面从8.1的源码入手分析(我能说我9.0的源码没看过吗)
根据scheduleXXX,handleXXX,performXXX,可以找到handleLaunchActivity,有两个地方调用了这个方法,scheduleLaunchActivity通过Handler调用,以及handleRelaunchActivity,当configuration改变的时候就会调用到该方法,即屏幕旋转的时候也会进入该方法
ActivityThread.java - handleRelaunchActivity
private void handleRelaunchActivity(ActivityClientRecord tmp) {
...
//注意最后一个参数getNonConfigInstance为true,如果是正常退出Activity的走到onDestory的该参数为false
handleDestroyActivity(r.token, false, configChanges, true);
...
handleLaunchActivity(r, currentIntent, "handleRelaunchActivity");
}
ActivityThread.java - handleDestroyActivity
private void handleDestroyActivity(IBinder token, boolean finishing,
int configChanges, boolean getNonConfigInstance) {
ActivityClientRecord r = performDestroyActivity(token, finishing,
configChanges, getNonConfigInstance);
}
ActivityThread.java - performDestroyActivity
private ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
int configChanges, boolean getNonConfigInstance) {
...
//此时为true,正常退出的为false
if (getNonConfigInstance) {
try {
//给ActivityClientRecord内的lastNonConfigurationInstances赋值
//调用对应Activity的retainNonConfigurationInstances方法
r.lastNonConfigurationInstances
= r.activity.retainNonConfigurationInstances();
} catch (Exception e) {
...
}
}
...
//最终回调到onDestroy方法
mInstrumentation.callActivityOnDestroy(r.activity);
...
}
Activity.java - retainNonConfigurationInstances
//9.0源码
NonConfigurationInstances retainNonConfigurationInstances() {
//FragmentActivity重写了onRetainNonConfigurationInstance方法
Object activity = onRetainNonConfigurationInstance();
HashMap<String, Object> children = onRetainNonConfigurationChildInstances();
FragmentManagerNonConfig fragments = mFragments.retainNestedNonConfig();
mFragments.doLoaderStart();
mFragments.doLoaderStop(true);
ArrayMap<String, LoaderManager> loaders = mFragments.retainLoaderNonConfig();
if (activity == null && children == null && fragments == null && loaders == null
&& mVoiceInteractor == null) {
return null;
}
//新建NonConfigurationInstances将上面获得的FragmentActivity
//内的NonConfigurationInstances添加进去
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.activity = activity;
nci.children = children;
nci.fragments = fragments;
nci.loaders = loaders;
if (mVoiceInteractor != null) {
mVoiceInteractor.retainInstance();
nci.voiceInteractor = mVoiceInteractor;
}
return nci;
}
FragmentActivity.java - onRetainNonConfigurationInstance
@Override
public final Object onRetainNonConfigurationInstance() {
Object custom = onRetainCustomNonConfigurationInstance();
//设置fragment的mRetaining为true
FragmentManagerNonConfig fragments = mFragments.retainNestedNonConfig();
if (fragments == null && mViewModelStore == null && custom == null) {
return null;
}
//创建一个NonConfigurationInstances,将此时的mViewModelStore设置进去
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.custom = custom;
nci.viewModelStore = mViewModelStore;
//fragments也保存起来了
nci.fragments = fragments;
return nci;
}
从上面的代码可以分析出r.lastNonConfigurationInstances最终设置的就是Activity.java内的NonConfigurationInstances()对象,该对象内的activity即代表FragmentActivity的NonConfigurationInstances()对象,现在回到handleRelaunchActivity,看handleLaunchActivity方法,调用到Activity的attach方法
Activity.java - attach
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor,
Window window, ActivityConfigCallback activityConfigCallback) {
...
//将ActivityClientRecord内的lastNonConfigurationInstances赋值给mLastNonConfigurationInstances
//表示此时该值为上次该Activity的NonConfigurationInstances对象
mLastNonConfigurationInstances = lastNonConfigurationInstances;
...
}
这时候回到getLastNonConfigurationInstance方法,此时mLastNonConfigurationInstances不为null,返回mLastNonConfigurationInstances.activity,即得到了上次FragmentActivity的NonConfigurationInstances对象,也就表示获得了上次该Activity内的mViewModelStore,所以就算屏幕旋转,系统也会根据getLastNonConfigurationInstance和onRetainNonConfigurationInstance来保存好ViewModelStore
FragmentActivity.java - onCreate
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
//都会先获取NonConfigurationInstances
//就算屏幕旋转了也能重新获取上次的mViewModelStore,在getViewModelStore能直接返回
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null && nc.viewModelStore != null && mViewModelStore == null) {
mViewModelStore = nc.viewModelStore;
}
if (savedInstanceState != null) {
//在onSaveInstanceState中mFragments.saveAllState()
//会将fragments、ViewModelStores等封装到FragmentManagerNonConfig内
mFragments.restoreAllState(p, nc != null ? nc.fragments : null);
}
}
FragmentActivity.java - onDestroy
@Override
protected void onDestroy() {
super.onDestroy();
if (mViewModelStore != null && !isChangingConfigurations()) {
mViewModelStore.clear();
}
mFragments.dispatchDestroy();
}