赞
踩
横竖屏切换的时候会调用ActivityThread中的handleRelaunchActivity()看名字就知道是要重新启动Activity,handleRelaunchActivity()有个handleRelaunchActivityInner(),从handleRelaunchActivityInner()这个方法开始进入正题:
- private void handleRelaunchActivityInner(ActivityClientRecord r, int configChanges,
- List<ResultInfo> pendingResults, List<ReferrerIntent> pendingIntents,
- PendingTransactionActions pendingActions, boolean startsNotResumed,
- Configuration overrideConfig, String reason) {
- // Preserve last used intent, it may be set from Activity#setIntent().
- final Intent customIntent = r.activity.mIntent;
- // Need to ensure state is saved.
- if (!r.paused) {
- performPauseActivity(r, false, reason, null /* pendingActions */);
- }
- if (!r.stopped) {
- callActivityOnStop(r, true /* saveState */, reason);
- }
-
- handleDestroyActivity(r.token, false, configChanges, true, reason);
-
- r.activity = null;
- r.window = null;
- r.hideForNow = false;
- r.nextIdle = null;
- // Merge any pending results and pending intents; don't just replace them
- if (pendingResults != null) {
- if (r.pendingResults == null) {
- r.pendingResults = pendingResults;
- } else {
- r.pendingResults.addAll(pendingResults);
- }
- }
- if (pendingIntents != null) {
- if (r.pendingIntents == null) {
- r.pendingIntents = pendingIntents;
- } else {
- r.pendingIntents.addAll(pendingIntents);
- }
- }
- r.startsNotResumed = startsNotResumed;
- r.overrideConfig = overrideConfig;
-
- handleLaunchActivity(r, pendingActions, customIntent);
- }
横竖屏切换的时候重启activity首先会先销毁activity所以这个方法的主要代码:
- private void handleRelaunchActivityInner(ActivityClientRecord r, int configChanges,
- List<ResultInfo> pendingResults, List<ReferrerIntent> pendingIntents,
- PendingTransactionActions pendingActions, boolean startsNotResumed,
- Configuration overrideConfig, String reason) {
- ...
-
- handleDestroyActivity(r.token, false, configChanges, true, reason);
-
- ...
-
- handleLaunchActivity(r, pendingActions, customIntent);
- }
先看handleDestroyActivity(r.token, false, configChanges, true, reason);这个方法,
- public void handleDestroyActivity(IBinder token, boolean finishing, int configChanges,
- boolean getNonConfigInstance, String reason) {
- ActivityClientRecord r = performDestroyActivity(token, finishing,
- configChanges, getNonConfigInstance, reason);
- if (r != null) {
- cleanUpPendingRemoveWindows(r, finishing);
- WindowManager wm = r.activity.getWindowManager();
- View v = r.activity.mDecor;
- if (v != null) {
- if (r.activity.mVisibleFromServer) {
- mNumVisibleActivities--;
- }
- IBinder wtoken = v.getWindowToken();
- if (r.activity.mWindowAdded) {
- if (r.mPreserveWindow) {
- // Hold off on removing this until the new activity's
- // window is being added.
- r.mPendingRemoveWindow = r.window;
- r.mPendingRemoveWindowManager = wm;
- // We can only keep the part of the view hierarchy that we control,
- // everything else must be removed, because it might not be able to
- // behave properly when activity is relaunching.
- r.window.clearContentView();
- } else {
- wm.removeViewImmediate(v);
- }
- }
- if (wtoken != null && r.mPendingRemoveWindow == null) {
- WindowManagerGlobal.getInstance().closeAll(wtoken,
- r.activity.getClass().getName(), "Activity");
- } else if (r.mPendingRemoveWindow != null) {
- // We're preserving only one window, others should be closed so app views
- // will be detached before the final tear down. It should be done now because
- // some components (e.g. WebView) rely on detach callbacks to perform receiver
- // unregister and other cleanup.
- WindowManagerGlobal.getInstance().closeAllExceptView(token, v,
- r.activity.getClass().getName(), "Activity");
- }
- r.activity.mDecor = null;
- }
- if (r.mPendingRemoveWindow == null) {
- // If we are delaying the removal of the activity window, then
- // we can't clean up all windows here. Note that we can't do
- // so later either, which means any windows that aren't closed
- // by the app will leak. Well we try to warning them a lot
- // about leaking windows, because that is a bug, so if they are
- // using this recreate facility then they get to live with leaks.
- WindowManagerGlobal.getInstance().closeAll(token,
- r.activity.getClass().getName(), "Activity");
- }
-
- // Mocked out contexts won't be participating in the normal
- // process lifecycle, but if we're running with a proper
- // ApplicationContext we need to have it tear down things
- // cleanly.
- Context c = r.activity.getBaseContext();
- if (c instanceof ContextImpl) {
- ((ContextImpl) c).scheduleFinalCleanup(
- r.activity.getClass().getName(), "Activity");
- }
- }
- if (finishing) {
- try {
- ActivityTaskManager.getService().activityDestroyed(token);
- } catch (RemoteException ex) {
- throw ex.rethrowFromSystemServer();
- }
- }
- mSomeActivitiesChanged = true;
- }
这个方法是要销毁Activity的,核心代码是performDestroyActivity(token, finishing, configChanges, getNonConfigInstance, reason)这句:
- 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) {
- activityClass = r.activity.getClass();
- r.activity.mConfigChangeFlags |= configChanges;
- if (finishing) {
- r.activity.mFinished = true;
- }
-
- performPauseActivityIfNeeded(r, "destroy");
-
- if (!r.stopped) {
- callActivityOnStop(r, false /* saveState */, "destroy");
- }
- 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);
- }
- }
- }
- try {
- r.activity.mCalled = false;
- mInstrumentation.callActivityOnDestroy(r.activity);
- if (!r.activity.mCalled) {
- throw new SuperNotCalledException(
- "Activity " + safeToComponentShortString(r.intent) +
- " did not call through to super.onDestroy()");
- }
- if (r.window != null) {
- r.window.closeAllPanels();
- }
- } catch (SuperNotCalledException e) {
- throw e;
- } catch (Exception e) {
- if (!mInstrumentation.onException(r.activity, e)) {
- throw new RuntimeException(
- "Unable to destroy activity " + safeToComponentShortString(r.intent)
- + ": " + e.toString(), e);
- }
- }
- r.setState(ON_DESTROY);
- }
- schedulePurgeIdler();
- // updatePendingActivityConfiguration() reads from mActivities to update
- // ActivityClientRecord which runs in a different thread. Protect modifications to
- // mActivities to avoid race.
- synchronized (mResourcesManager) {
- mActivities.remove(token);
- }
- StrictMode.decrementExpectedActivityCount(activityClass);
- return r;
- }
这里我们看到了熟悉的retainNonConfigurationInstances():
- ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
- int configChanges, boolean getNonConfigInstance, String reason) {
- ...
- 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);
- }
- }
- }
- ...
- }
先看这个判断if (getNonConfigInstance) ,这个getNonConfigInstance如果是true就会走进去调用我们熟悉的retainNonConfigurationInstances(),看到这个getNonConfigInstance是参数传进来,看一下调用追溯到handleDestroyActivity(r.token, false, configChanges, true, reason);这个方法,发现就是true所以会进入判断调用:
r.lastNonConfigurationInstances = r.activity.retainNonConfigurationInstances();
先分析:r.activity.retainNonConfigurationInstances();这个会调用到Activity的retainNonConfigurationInstances();方法:
- 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;
- }
这个方法第一句就会调用onRetainNonConfigurationInstance(),这个方法的实现是在ComponentActivity:
- public final Object onRetainNonConfigurationInstance() {
- 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;
- }
上篇学习ViewModel原理的时候我们分析过了这个方法就是用来保存viewModelStore的,这里再扩展一点,这个方法的第一句是Object custom = onRetainCustomNonConfigurationInstance();这个方法会在横竖屏切换的时候切换,我写了个例子大家看一下效果:
- public class MyActivity extends AppCompatActivity {
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- ActivityBinding binding = ActivityBinding.inflate(getLayoutInflater());
- setContentView(binding.getRoot());
- Log.e("ViewModel", "onCreate");
- }
-
- @Override
- protected void onSaveInstanceState(@NonNull Bundle outState) {
- Log.e("ViewModel", "onSaveInstanceState");
- super.onSaveInstanceState(outState);
- }
-
- @Override
- protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
- Log.e("ViewModel", "onRestoreInstanceState");
- super.onRestoreInstanceState(savedInstanceState);
- }
-
- @Nullable
- @Override
- public Object onRetainCustomNonConfigurationInstance() {
- Log.e("ViewModel", "onRetainCustomNonConfigurationInstance");
- return super.onRetainCustomNonConfigurationInstance();
- }
-
- @Override
- protected void onRestart() {
- super.onRestart();
- Log.e("ViewModel", "onRestart");
- }
-
- @Override
- protected void onStart() {
- super.onStart();
- Log.e("ViewModel", "onStart");
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- Log.e("ViewModel", "onResume");
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- Log.e("ViewModel", "onPause");
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- Log.e("ViewModel", "onStop");
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- Log.e("ViewModel","onDestroy");
- }
-
-
-
- }
不横竖屏切换正常调用顺序:
横竖屏切换时的调用顺序:
可以看到 Object custom = onRetainCustomNonConfigurationInstance();每次在横竖屏切换销毁之前都会调用,所以我们可以通过这个方法保存我们自己的数据。它和viewModelStore一样被存在
ComponentActivity中的静态内部类NonConfigurationInstances:
- static final class NonConfigurationInstances {
- Object custom;
- ViewModelStore viewModelStore;
- }
然后作为返回值返回到Activity中的:
然后通过Activity中的静态内部类NonConfigurationInstances:
- static final class NonConfigurationInstances {
- Object activity;
- HashMap<String, Object> children;
- FragmentManagerNonConfig fragments;
- ArrayMap<String, LoaderManager> loaders;
- VoiceInteractor voiceInteractor;
- }
最后NonConfigurationInstances做为返回值返回到ActivityThread中的这句:
r.lastNonConfigurationInstances = r.activity.retainNonConfigurationInstances();
是不是很熟悉:
- ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
- int configChanges, boolean getNonConfigInstance, String reason) {
- ...
- 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);
- }
- }
- }
- ...
- }
返回值中包含我们的ViewModelStore,最后它被赋值保存在了r对象的lastNonConfigurationInstances中,这个r对象就是ActivityClientRecord。
好了,现在知道了onRetainNonConfigurationInstance()的调用逻辑了。
现在知道在横竖屏切换activity销毁之前viewModelStore被ActivityClientRecord在ActivityTread中保存了下来,顺便分析一下保存之后在activity销毁了如何在重建activity后恢复:
- private void handleRelaunchActivityInner(ActivityClientRecord r, int configChanges,
- List<ResultInfo> pendingResults, List<ReferrerIntent> pendingIntents,
- PendingTransactionActions pendingActions, boolean startsNotResumed,
- Configuration overrideConfig, String reason) {
- ...
-
- handleDestroyActivity(r.token, false, configChanges, true, reason);
-
- ...
-
- handleLaunchActivity(r, pendingActions, customIntent);
- }
分析 handleLaunchActivity(r, pendingActions, customIntent);,这个r对象就是上面存储了ViewModelStore的对象,我们详细分析一下:
- public Activity handleLaunchActivity(ActivityClientRecord r,
- PendingTransactionActions pendingActions, Intent customIntent) {
- // If we are getting ready to gc after going to the background, well
- // we are back active so skip it.
- unscheduleGcIdler();
- mSomeActivitiesChanged = true;
-
- if (r.profilerInfo != null) {
- mProfiler.setProfiler(r.profilerInfo);
- mProfiler.startProfiling();
- }
-
- // Make sure we are running with the most recent config.
- handleConfigurationChanged(null, null);
-
- if (localLOGV) Slog.v(
- TAG, "Handling launch of " + r);
-
- // Initialize before creating the activity
- if (!ThreadedRenderer.sRendererDisabled
- && (r.activityInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
- HardwareRenderer.preload();
- }
- WindowManagerGlobal.initialize();
-
- // Hint the GraphicsEnvironment that an activity is launching on the process.
- GraphicsEnvironment.hintActivityLaunch();
-
- final Activity a = performLaunchActivity(r, customIntent);
-
- if (a != null) {
- r.createdConfig = new Configuration(mConfiguration);
- reportSizeConfigurations(r);
- if (!r.activity.mFinished && pendingActions != null) {
- pendingActions.setOldState(r.state);
- pendingActions.setRestoreInstanceState(true);
- pendingActions.setCallOnPostCreate(true);
- }
- } else {
- // If there was an error, for any reason, tell the activity manager to stop us.
- try {
- ActivityTaskManager.getService()
- .finishActivity(r.token, Activity.RESULT_CANCELED, null,
- Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
- } catch (RemoteException ex) {
- throw ex.rethrowFromSystemServer();
- }
- }
-
- return a;
- }
核心代码:
- 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;
- if (r.packageInfo == null) {
- r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
- Context.CONTEXT_INCLUDE_CODE);
- }
-
- ComponentName component = r.intent.getComponent();
- if (component == null) {
- component = r.intent.resolveActivity(
- mInitialApplication.getPackageManager());
- r.intent.setComponent(component);
- }
-
- if (r.activityInfo.targetActivity != null) {
- component = new ComponentName(r.activityInfo.packageName,
- r.activityInfo.targetActivity);
- }
-
- ContextImpl appContext = createBaseContextForActivity(r);
- Activity activity = null;
- try {
- 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 {
- Application app = r.packageInfo.makeApplication(false, mInstrumentation);
-
- if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
- if (localLOGV) Slog.v(
- TAG, r + ": app=" + app
- + ", appName=" + app.getPackageName()
- + ", pkg=" + r.packageInfo.getPackageName()
- + ", comp=" + r.intent.getComponent().toShortString()
- + ", dir=" + r.packageInfo.getAppDir());
-
- if (activity != null) {
- CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
- Configuration config = new Configuration(mCompatConfiguration);
- if (r.overrideConfig != null) {
- config.updateFrom(r.overrideConfig);
- }
- if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
- + r.activityInfo.name + " with config " + config);
- Window window = null;
- if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
- window = r.mPendingRemoveWindow;
- r.mPendingRemoveWindow = null;
- r.mPendingRemoveWindowManager = null;
- }
-
- // Activity resources must be initialized with the same loaders as the
- // application context.
- appContext.getResources().addLoaders(
- app.getResources().getLoaders().toArray(new ResourcesLoader[0]));
-
- appContext.setOuterContext(activity);
- 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);
-
- if (customIntent != null) {
- activity.mIntent = customIntent;
- }
- r.lastNonConfigurationInstances = null;
- checkAndBlockForNetworkAccess();
- activity.mStartedActivity = false;
- int theme = r.activityInfo.getThemeResource();
- if (theme != 0) {
- activity.setTheme(theme);
- }
-
- activity.mCalled = false;
- if (r.isPersistable()) {
- mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
- } else {
- mInstrumentation.callActivityOnCreate(activity, r.state);
- }
- if (!activity.mCalled) {
- throw new SuperNotCalledException(
- "Activity " + r.intent.getComponent().toShortString() +
- " did not call through to super.onCreate()");
- }
- r.activity = activity;
- mLastReportedWindowingMode.put(activity.getActivityToken(),
- config.windowConfiguration.getWindowingMode());
- }
- r.setState(ON_CREATE);
-
- // updatePendingActivityConfiguration() reads from mActivities to update
- // ActivityClientRecord which runs in a different thread. Protect modifications to
- // mActivities to avoid race.
- synchronized (mResourcesManager) {
- mActivities.put(r.token, r);
- }
-
- } 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;
- }
核心代码:
- private void handleFixedRotationAdjustments(@NonNull IBinder token,
- @Nullable FixedRotationAdjustments fixedRotationAdjustments,
- @Nullable Configuration overrideConfig) {
-
- ...
- 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);
-
- ...
-
- return activity;
- }
这个attach方法的一个参数r.lastNonConfigurationInstances,这个很熟悉就是r.lastNonConfigurationInstances = r.activity.retainNonConfigurationInstances()这个就是activity的NonConfigurationInstances用来保存ViewModelStore,这样保存的ViewModelStore就被传到了Activity的attach方法中。
接下来我们分析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, IBinder assistToken) {
- attachBaseContext(context);
-
- mFragments.attachHost(null /*parent*/);
-
- mWindow = new PhoneWindow(this, window, activityConfigCallback);
- mWindow.setWindowControllerCallback(mWindowControllerCallback);
- mWindow.setCallback(this);
- mWindow.setOnWindowDismissedCallback(this);
- mWindow.getLayoutInflater().setPrivateFactory(this);
- if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
- mWindow.setSoftInputMode(info.softInputMode);
- }
- if (info.uiOptions != 0) {
- mWindow.setUiOptions(info.uiOptions);
- }
- mUiThread = Thread.currentThread();
-
- mMainThread = aThread;
- mInstrumentation = instr;
- mToken = token;
- mAssistToken = assistToken;
- mIdent = ident;
- mApplication = application;
- mIntent = intent;
- mReferrer = referrer;
- mComponent = intent.getComponent();
- mActivityInfo = info;
- mTitle = title;
- mParent = parent;
- mEmbeddedID = id;
- mLastNonConfigurationInstances = lastNonConfigurationInstances;
- if (voiceInteractor != null) {
- if (lastNonConfigurationInstances != null) {
- mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
- } else {
- mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
- Looper.myLooper());
- }
- }
-
- mWindow.setWindowManager(
- (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
- mToken, mComponent.flattenToString(),
- (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
- if (mParent != null) {
- mWindow.setContainer(mParent.getWindow());
- }
- mWindowManager = mWindow.getWindowManager();
- mCurrentConfig = config;
-
- mWindow.setColorMode(info.colorMode);
- mWindow.setPreferMinimalPostProcessing(
- (info.flags & ActivityInfo.FLAG_PREFER_MINIMAL_POST_PROCESSING) != 0);
-
- setAutofillOptions(application.getAutofillOptions());
- setContentCaptureOptions(application.getContentCaptureOptions());
- }
我们要找的核心逻辑:
mLastNonConfigurationInstances = lastNonConfigurationInstances;
这样就被缓存在了Activity中的mLastNonConfigurationInstances成员变量中,这个mLastNonConfigurationInstances是Activity的NonConfigurationInstances:
这个 NonConfigurationInstances中的Object activity是ComponentActivity中的
再看一下这个mLastNonConfigurationInstances是啥时候用的:
这个 mLastNonConfigurationInstances.activity就是ComponentActivity存储ViewModelStore的NonConfigurationInstances。
好了一切都归于平静了。
总结一下:在横竖屏切换的时候会调用ActivityThread中的handleRelaunchActivity方法,handleRelaunchActivity方法的核心是handleRelaunchActivityInner方法,在handleRelaunchActivityInner方法中处理了activity的销毁和重建,在销毁之前把ViewModelStore保存起来,在重建的时候把保存的数据通过Activity的attach方法传入新的Activity中,这样就实现了ViewModel在横竖屏切换的时候不会丢失。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。