- 相关类定义理解:
ViewModelStoreOwner:接口类,表示ViewModleStore的持有者,向外提供ViewModleStore
ViewModleStore:使用HashMap管理ViewModle
ViewModelProvider:用于获取ViewModle实例,并内置KeyedFactory,NewInstanceFactory,AndroidViewModelFactor形式创建ViewModle. 也可自己实现Factory接口来创建自己的ViewModle.
理解viewmodle,就从用于获取ViewModle实例的ViewModelProvider开始。
- ViewModle实例化流程
以下ViewModelProvider的构造方法
public class ViewModelProvider {
private final Factory mFactory;
private final ViewModelStore mViewModelStore;
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;
}
}
在Activity中用以下方法获取一个ViewModel
val viewModel = ViewModelProvider(activity).get(AViewModel::class.java)
那么会进入到ViewModelProvider的public ViewModelProvider(@NonNull ViewModelStoreOwner owner)这个构造方法.
1.传的activity变成了ViewModelStoreOwner,因为ComponentActivity实现了ViewModelStoreOwner接口 ,看看ComponentActivity的代码
public class ComponentActivity extends androidx.core.app.ComponentActivity implements .. ViewModelStoreOwner,
HasDefaultViewModelProviderFactory,
SavedStateRegistryOwner,
...{
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;
}
@SuppressWarnings("WeakerAccess") /* synthetic access */
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();
}
}
}
@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;
}
}
2.ComponentActivity也实现HasDefaultViewModelProviderFactory接口,返回一个SavedStateViewModelFactory工厂对象
那么接口下来再看ViewModelProvider.get()方法怎么获取ViewModel实例
private static final String DEFAULT_KEY =
"androidx.lifecycle.ViewModelProvider.DefaultKey";
@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);
}
@SuppressWarnings("unchecked")
@NonNull
@MainThread
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;
}
1.通过DEFAULT_KEY+canonicalName组成Key,并ViewModelStore中Key获取ViewModel,ViewModelStore内部用HashMap存储ViewModel
2.目前我们没有实例化过ViewModel,那么在ViewModelStore里肯定获取不到,就进入以下判断
if (mFactory instanceof KeyedFactory) {
viewModel = ((KeyedFactory) mFactory).create(key, modelClass);
} else {
viewModel = mFactory.create(modelClass);
}
mFactory在构造方法中已经赋值,为SavedStateViewModelFactory工厂对象,而SavedStateViewModelFactory也实现了KeyedFactory接口,那自然进入到SavedStateViewModelFactory.create中
public final class SavedStateViewModelFactory extends ViewModelProvider.KeyedFactory {
public SavedStateViewModelFactory(@Nullable Application application,
@NonNull SavedStateRegistryOwner owner,
@Nullable Bundle defaultArgs) {
mSavedStateRegistry = owner.getSavedStateRegistry();
mLifecycle = owner.getLifecycle();
mDefaultArgs = defaultArgs;
mApplication = application;
mFactory = application != null
? ViewModelProvider.AndroidViewModelFactory.getInstance(application)
: ViewModelProvider.NewInstanceFactory.getInstance();
}
......
@NonNull
@Override
public <T extends ViewModel> T create(@NonNull String key, @NonNull Class<T> modelClass) {
//判断需要实例化的ViewModel是否继承了AndroidViewModel
boolean isAndroidViewModel = AndroidViewModel.class.isAssignableFrom(modelClass);
Constructor<T> constructor;
if (isAndroidViewModel && mApplication != null) {
constructor = findMatchingConstructor(modelClass, ANDROID_VIEWMODEL_SIGNATURE);
} else {
constructor = findMatchingConstructor(modelClass, VIEWMODEL_SIGNATURE);
}
// doesn't need SavedStateHandle
if (constructor == null) {
return mFactory.create(modelClass);
}
SavedStateHandleController controller = SavedStateHandleController.create(
mSavedStateRegistry, mLifecycle, key, mDefaultArgs);
try {
T viewmodel;
if (isAndroidViewModel && mApplication != null) {
viewmodel = constructor.newInstance(mApplication, controller.getHandle());
} else {
viewmodel = constructor.newInstance(controller.getHandle());
}
viewmodel.setTagIfAbsent(TAG_SAVED_STATE_HANDLE_CONTROLLER, controller);
return viewmodel;
} catch (IllegalAccessException e) {
throw new RuntimeException("Failed to access " + modelClass, e);
} catch (InstantiationException e) {
throw new RuntimeException("A " + modelClass + " cannot be instantiated.", e);
} catch (InvocationTargetException e) {
throw new RuntimeException("An exception happened in constructor of "
+ modelClass, e.getCause());
}
}
private static final Class<?>[] ANDROID_VIEWMODEL_SIGNATURE = new Class[]{Application.class,
SavedStateHandle.class};
private static final Class<?>[] VIEWMODEL_SIGNATURE = new Class[]{SavedStateHandle.class};
@SuppressWarnings("unchecked")
private static <T> Constructor<T> findMatchingConstructor(Class<T> modelClass,
Class<?>[] signature) {
for (Constructor<?> constructor : modelClass.getConstructors()) {
Class<?>[] parameterTypes = constructor.getParameterTypes();
if (Arrays.equals(signature, parameterTypes)) {
return (Constructor<T>) constructor;
}
}
return null;
}
}
- SavedStateViewModelFactory的构造方法中,mFactory是AndroidViewModelFactory对象,因为上面贴出的 ComponentActivity的代码中实例化SavedStateViewModelFactory时,传了Application参数
2.SavedStateViewModelFactory.create中
2.1.判断需要实例化的ViewModel是否继承了AndroidViewModel
2.2.通过findMatchingConstructor方法和ANDROID_VIEWMODEL_SIGNATURE/VIEWMODEL_SIGNATURE,在你需要实例化的ViewModel中匹配构造函数
2.3.如你的ViewModel中没有相关构造函数,那么就直接使用AndroidViewModelFactory.create来帮你实例化ViewModel
public static class AndroidViewModelFactory extends ViewModelProvider.NewInstanceFactory {
....
@NonNull
@Override
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
if (AndroidViewModel.class.isAssignableFrom(modelClass)) {
//noinspection TryWithIdenticalCatches
try {
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);
}
}
public static class NewInstanceFactory implements Factory {
....
@SuppressWarnings("ClassNewInstance")
@NonNull
@Override
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);
}
}
}
AndroidViewModelFactory中最终通过newInstance反射获取ViewModel实例
回到ViewModelProvider.get里将通过以上流程获取到的ViewModel实例 put到ViewModelStore里,至此,获取ViewModel实例化流程已走完.
- ViewModel销毁(viewModelScope销毁)
在ComponentActivity通过Lifecycle获取生命周期变化,当状态 == Lifecycle.Event.ON_DESTROY时, 会调用所有ViewModel.clear(),并将ViewModelStore中HashMap清空
ComponentActivity.java
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();
}
}
}
});
ViewModelStore.java
public class ViewModelStore {
private final HashMap<String, ViewModel> mMap = new HashMap<>();
....
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.clear();
}
mMap.clear();
}
}
ViewModel.Java
public abstract class ViewModel {
private final Map<String, Object> mBagOfTags = new HashMap<>();
private volatile boolean mCleared = false;
....
@MainThread
final void clear() {
mCleared = true;
// Since clear() is final, this method is still called on mock objects
// and in those cases, mBagOfTags is null. It'll always be empty though
// because setTagIfAbsent and getTag are not final so we can skip
// clearing it
if (mBagOfTags != null) {
synchronized (mBagOfTags) {
for (Object value : mBagOfTags.values()) {
// see comment for the similar call in setTagIfAbsent
closeWithRuntimeException(value);
}
}
}
onCleared();
}
private static void closeWithRuntimeException(Object obj) {
if (obj instanceof Closeable) {
try {
((Closeable) obj).close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
so,所有如果你的ViewModel想在销毁时候做某些操作,可以重写onCleared()方法来实现,
如果你在ViewModel用到了viewModelScope协程,它也是ViewModel.clear里取消, 看看viewModelScope代码
public val ViewModel.viewModelScope: CoroutineScope
get() {
val scope: CoroutineScope? = this.getTag(JOB_KEY)
if (scope != null) {
return scope
}
return setTagIfAbsent(
JOB_KEY,
CloseableCoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
)
}
internal class CloseableCoroutineScope(context: CoroutineContext) : Closeable, CoroutineScope {
override val coroutineContext: CoroutineContext = context
override fun close() {
coroutineContext.cancel()
}
}
viewModelScope其实是CloseableCoroutineScope,并实现了Closeable接口,在close()被调用时就执行coroutineContext.cancel()
使用ViewModel.setTagIfAbsent方法 将这个CloseableCoroutineScope添加到了 ViewModel的mBagOfTags中, ViewModel.clear执行时就会for出mBagOfTags每个值,到closeWithRuntimeException方法 变为Closeable对象,执行close
- ViewModel复用流程
ViewModel可以在Activity配置变化后重新复用,能复用就代表ViewModel被保存起来,并在Activity重建后重新赋值 在上面分析ViewModel实例化流程已经看到 ViewModel 是保存在ViewModelStore里,那么需要实现Activity重建后复用, 那就是将ViewModelStore保存起来,重建后复用ViewModelStore,自然ViewModel就是复用了.
再看看ComponentActivity中获取ViewModelStore代码
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;
}
@SuppressWarnings("WeakerAccess") /* synthetic access */
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();
}
}
}
代码里是先从NonConfigurationInstances中获取viewModelStore,获取不到才new一个,那么这个NonConfigurationInstances就是被保存起来的
ComponentActivity.java
static final class NonConfigurationInstances {
Object custom;
ViewModelStore viewModelStore;
}
Activity.java
public Object getLastNonConfigurationInstance() {
return mLastNonConfigurationInstances != null
? mLastNonConfigurationInstances.activity : null;
}
static final class NonConfigurationInstances {
Object activity;
HashMap<String, Object> children;
FragmentManagerNonConfig fragments;
ArrayMap<String, LoaderManager> loaders;
VoiceInteractor voiceInteractor;
}
从上面三段代码得知 viewModelStore被包在ComponentActivity的静态NonConfigurationInstances类里,
而Activity的静态NonConfigurationInstances类中的Object activity,正是指向ComponentActivity的NonConfigurationInstances
那么现在源头指向了Activity.mLastNonConfigurationInstances
在Activity中搜索可见mLastNonConfigurationInstances是在Activity.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) {
......
mLastNonConfigurationInstances = lastNonConfigurationInstances;
....
}
就是说Activity销毁时,将lastNonConfigurationInstances保存起来,待新的Activity起来后在attach里将值赋值给新的mLastNonConfigurationInstances
Activity.attach在哪里被调用?在ActivityThread里
Activity销毁入口在哪里?
ActivityThread里有handleDestroyActivity,handleLaunchActivity等各个生命周期入口,还有一个handleRelaunchActivity
配置变化导致的Activity重建就会执行ActivityThread.handleRelaunchActivity
public void handleRelaunchActivity(ActivityClientRecord tmp,
PendingTransactionActions pendingActions) {
...
ActivityClientRecord r = mActivities.get(tmp.token);
r.activity.mConfigChangeFlags |= configChanges;
r.mPreserveWindow = tmp.mPreserveWindow;
r.activity.mChangingConfigurations = true;
handleRelaunchActivityInner(r, configChanges, tmp.pendingResults, tmp.pendingIntents,
pendingActions, tmp.startsNotResumed, tmp.overrideConfig, "handleRelaunchActivity");
...
}
重点是调用了 handleRelaunchActivityInner
private void handleRelaunchActivityInner(ActivityClientRecord r, int configChanges,
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingIntents,
PendingTransactionActions pendingActions, boolean startsNotResumed,
Configuration overrideConfig, String reason) {
final Intent customIntent = r.activity.mIntent;
//activity是否已 Pause?,没有就Pause,会走到Activity.onPause
if (!r.paused) {
performPauseActivity(r, false, reason, null /* pendingActions */);
}
//activity是否已 stop?,没有就stop,会走到Activity.onStop
if (!r.stopped) {
callActivityOnStop(r, true /* saveState */, reason);
}
//销毁当前activity,
handleDestroyActivity(r.token, false, configChanges, true, reason);
....
//销毁后再创建Activity
handleLaunchActivity(r, pendingActions, customIntent);
}
看看handleDestroyActivity
public void handleDestroyActivity(IBinder token, boolean finishing, int configChanges,
boolean getNonConfigInstance, String reason) {
ActivityClientRecord r = performDestroyActivity(token, finishing,
configChanges, getNonConfigInstance, reason);
.....
}
ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
int configChanges, boolean getNonConfigInstance, String reason) {
ActivityClientRecord r = mActivities.get(token);
Class<? extends Activity> activityClass = null;
if (localLOGV) Slog.v(TAG, "Performing finish of " + r);
if (r != null) {
....
if (getNonConfigInstance) {
try {
r.lastNonConfigurationInstances
= r.activity.retainNonConfigurationInstances();
} catch (Exception e) {
if (!mInstrumentation.onException(r.activity, e)) {
throw new RuntimeException(
"Unable to retain activity "
+ r.intent.getComponent().toShortString()
+ ": " + e.toString(), e);
}
}
}
....
r.setState(ON_DESTROY);
}
return r;
}
来到performDestroyActivity中 只要 getNonConfigInstance为true,就会执行r.activity.retainNonConfigurationInstances(),
而getNonConfigInstance是从handleRelaunchActivityInner中调用handleDestroyActivity传进来的,值为true
r.activity.retainNonConfigurationInstances()就是Activity中的retainNonConfigurationInstances()方法
Activity.Java
NonConfigurationInstances retainNonConfigurationInstances() {
Object activity = onRetainNonConfigurationInstance();
HashMap<String, Object> children = onRetainNonConfigurationChildInstances();
FragmentManagerNonConfig fragments = mFragments.retainNestedNonConfig();
// We're already stopped but we've been asked to retain.
// Our fragments are taken care of but we need to mark the loaders for retention.
// In order to do this correctly we need to restart the loaders first before
// handing them off to the next activity.
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 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;
}
这里直接实例化了一个Activity.NonConfigurationInstances对象,刚才已经得知Activity.NonConfigurationInstances.activity 就是指向 ComponentActivity$NonConfigurationInstances,
而这里的Activity.NonConfigurationInstances.activity 有onRetainNonConfigurationChildInstances()返回赋值的,
这个方法在Activity中返回是Null,但在 ComponentActivity中重写了这个方法
ComponentActivity.java
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;
nci.viewModelStore = viewModelStore;
return nci;
}
那么到这里已经分析出Activity在销毁前执行activity.retainNonConfigurationInstances()将数据保存在ActivityClientRecord.lastNonConfigurationInstancesz中
刚才的handleRelaunchActivityInner方法中是先执行handleDestroyActivity销毁activity,再使用handleLaunchActivity重建activity
public Activity handleLaunchActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions, Intent customIntent) {
.....
final Activity a = performLaunchActivity(r, customIntent);
....
return a;
}
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ActivityInfo aInfo = r.activityInfo;
....
Activity activity = null;
try {
//重建Activity对象
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
try {
....
//执行Activity.attach
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.configCallback,
r.assistToken);
....
//执行Activity.OnCreate生命周期
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
}
...
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to start activity " + component
+ ": " + e.toString(), e);
}
}
return activity;
}
最终在performLaunchActivity中重建了Activity,并直接调用 activity.attach方法,将保存在 ActivityClientRecord.lastNonConfigurationInstancesz的值还原给activity.mLastNonConfigurationInstances
整个复用流程已经分析完成,简单总结一下:
Activity配置变更导致的销毁/重建,会执行ActivityThread.handleRelaunchActivity,
ActivityThread.handleRelaunchActivity会先执行handleDestroyActivity流程,再执行handleLaunchActivity流程
1.在handleDestroyActivity流程中的performDestroyActivity方法中调用activity.retainNonConfigurationInstances()将数据保存在ActivityClientRecord.lastNonConfigurationInstancesz中
2.在handleLaunchActivity流程中的performLaunchActivity方法中将Activity重建,并调用用activity.attach,将数据还原