From b1294597c6bca499c62f182018ec27c769d9afef Mon Sep 17 00:00:00 2001 From: Ian Lake Date: Wed, 19 Sep 2018 11:01:13 -0700 Subject: [PATCH] Add pre and post callbacks to ActivityLifecycleCallbacks For each lifecycle event exposed in ActivityLifecycleCallbacks, an additional pair of methods have been added to give developers a reliable callback before and after each lifecycle event. The existing callbacks cannot be used for this as they are called as part of the super implementation and therefore can run at any point in relation to the other code in the Activity. Test: manual BUG: 116118635 Change-Id: If91f3f3248f9d7cf14aac2fe24ce14d92b8d05d3 --- api/current.txt | 14 ++ core/java/android/app/Activity.java | 16 ++ core/java/android/app/Application.java | 279 +++++++++++++++++++++++++ 3 files changed, 309 insertions(+) diff --git a/api/current.txt b/api/current.txt index d897162b1aa3f..6892579dc5476 100755 --- a/api/current.txt +++ b/api/current.txt @@ -4296,6 +4296,20 @@ package android.app { method public abstract void onActivityCreated(android.app.Activity, android.os.Bundle); method public abstract void onActivityDestroyed(android.app.Activity); method public abstract void onActivityPaused(android.app.Activity); + method public default void onActivityPostCreated(android.app.Activity, android.os.Bundle); + method public default void onActivityPostDestroyed(android.app.Activity); + method public default void onActivityPostPaused(android.app.Activity); + method public default void onActivityPostResumed(android.app.Activity); + method public default void onActivityPostSaveInstanceState(android.app.Activity, android.os.Bundle); + method public default void onActivityPostStarted(android.app.Activity); + method public default void onActivityPostStopped(android.app.Activity); + method public default void onActivityPreCreated(android.app.Activity, android.os.Bundle); + method public default void onActivityPreDestroyed(android.app.Activity); + method public default void onActivityPrePaused(android.app.Activity); + method public default void onActivityPreResumed(android.app.Activity); + method public default void onActivityPreSaveInstanceState(android.app.Activity, android.os.Bundle); + method public default void onActivityPreStarted(android.app.Activity); + method public default void onActivityPreStopped(android.app.Activity); method public abstract void onActivityResumed(android.app.Activity); method public abstract void onActivitySaveInstanceState(android.app.Activity, android.os.Bundle); method public abstract void onActivityStarted(android.app.Activity); diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 2ee266de4c774..2acae1cf8bace 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -1588,11 +1588,13 @@ public class Activity extends ContextThemeWrapper * @param outState The bundle to save the state to. */ final void performSaveInstanceState(@NonNull Bundle outState) { + getApplication().dispatchActivityPreSaveInstanceState(this, outState); onSaveInstanceState(outState); saveManagedDialogs(outState); mActivityTransitionState.saveState(outState); storeHasCurrentPermissionRequest(outState); if (DEBUG_LIFECYCLE) Slog.v(TAG, "onSaveInstanceState " + this + ": " + outState); + getApplication().dispatchActivityPostSaveInstanceState(this, outState); } /** @@ -1606,11 +1608,13 @@ public class Activity extends ContextThemeWrapper */ final void performSaveInstanceState(@NonNull Bundle outState, @NonNull PersistableBundle outPersistentState) { + getApplication().dispatchActivityPreSaveInstanceState(this, outState); onSaveInstanceState(outState, outPersistentState); saveManagedDialogs(outState); storeHasCurrentPermissionRequest(outState); if (DEBUG_LIFECYCLE) Slog.v(TAG, "onSaveInstanceState " + this + ": " + outState + ", " + outPersistentState); + getApplication().dispatchActivityPostSaveInstanceState(this, outState); } /** @@ -7195,6 +7199,7 @@ public class Activity extends ContextThemeWrapper @UnsupportedAppUsage final void performCreate(Bundle icicle, PersistableBundle persistentState) { + getApplication().dispatchActivityPreCreated(this, icicle); mCanEnterPictureInPicture = true; restoreHasCurrentPermissionRequest(icicle); if (persistentState != null) { @@ -7209,6 +7214,7 @@ public class Activity extends ContextThemeWrapper com.android.internal.R.styleable.Window_windowNoDisplay, false); mFragments.dispatchActivityCreated(); mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions()); + getApplication().dispatchActivityPostCreated(this, icicle); } final void performNewIntent(@NonNull Intent intent) { @@ -7217,6 +7223,7 @@ public class Activity extends ContextThemeWrapper } final void performStart(String reason) { + getApplication().dispatchActivityPreStarted(this); mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions()); mFragments.noteStateNotSaved(); mCalled = false; @@ -7284,6 +7291,7 @@ public class Activity extends ContextThemeWrapper } mActivityTransitionState.enterReady(this); + getApplication().dispatchActivityPostStarted(this); } /** @@ -7338,6 +7346,7 @@ public class Activity extends ContextThemeWrapper } final void performResume(boolean followedByPause, String reason) { + getApplication().dispatchActivityPreResumed(this); performRestart(true /* start */, reason); mFragments.execPendingActions(); @@ -7387,9 +7396,11 @@ public class Activity extends ContextThemeWrapper "Activity " + mComponent.toShortString() + " did not call through to super.onPostResume()"); } + getApplication().dispatchActivityPostResumed(this); } final void performPause() { + getApplication().dispatchActivityPrePaused(this); mDoReportFullyDrawn = false; mFragments.dispatchPause(); mCalled = false; @@ -7402,6 +7413,7 @@ public class Activity extends ContextThemeWrapper "Activity " + mComponent.toShortString() + " did not call through to super.onPause()"); } + getApplication().dispatchActivityPostPaused(this); } final void performUserLeaving() { @@ -7417,6 +7429,7 @@ public class Activity extends ContextThemeWrapper mCanEnterPictureInPicture = false; if (!mStopped) { + getApplication().dispatchActivityPreStopped(this); if (mWindow != null) { mWindow.closeAllPanels(); } @@ -7451,11 +7464,13 @@ public class Activity extends ContextThemeWrapper } mStopped = true; + getApplication().dispatchActivityPostStopped(this); } mResumed = false; } final void performDestroy() { + getApplication().dispatchActivityPreDestroyed(this); mDestroyed = true; mWindow.destroy(); mFragments.dispatchDestroy(); @@ -7465,6 +7480,7 @@ public class Activity extends ContextThemeWrapper if (mVoiceInteractor != null) { mVoiceInteractor.detachActivity(); } + getApplication().dispatchActivityPostDestroyed(this); } final void dispatchMultiWindowModeChanged(boolean isInMultiWindowMode, diff --git a/core/java/android/app/Application.java b/core/java/android/app/Application.java index 68b745d54bc0f..e12942f248d43 100644 --- a/core/java/android/app/Application.java +++ b/core/java/android/app/Application.java @@ -65,13 +65,144 @@ public class Application extends ContextWrapper implements ComponentCallbacks2 { public LoadedApk mLoadedApk; public interface ActivityLifecycleCallbacks { + + /** + * Called as the first step of the Activity being created. This is always called before + * {@link Activity#onCreate}. + */ + default void onActivityPreCreated(@NonNull Activity activity, + @Nullable Bundle savedInstanceState) { + } + + /** + * Called when the Activity calls {@link Activity#onCreate super.onCreate()}. + */ void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState); + + /** + * Called as the last step of the Activity being created. This is always called after + * {@link Activity#onCreate}. + */ + default void onActivityPostCreated(@NonNull Activity activity, + @Nullable Bundle savedInstanceState) { + } + + /** + * Called as the first step of the Activity being started. This is always called before + * {@link Activity#onStart}. + */ + default void onActivityPreStarted(@NonNull Activity activity) { + } + + /** + * Called when the Activity calls {@link Activity#onStart super.onStart()}. + */ void onActivityStarted(@NonNull Activity activity); + + /** + * Called as the last step of the Activity being started. This is always called after + * {@link Activity#onStart}. + */ + default void onActivityPostStarted(@NonNull Activity activity) { + } + + /** + * Called as the first step of the Activity being resumed. This is always called before + * {@link Activity#onResume}. + */ + default void onActivityPreResumed(@NonNull Activity activity) { + } + + /** + * Called when the Activity calls {@link Activity#onResume super.onResume()}. + */ void onActivityResumed(@NonNull Activity activity); + + /** + * Called as the last step of the Activity being resumed. This is always called after + * {@link Activity#onResume} and {@link Activity#onPostResume}. + */ + default void onActivityPostResumed(@NonNull Activity activity) { + } + + /** + * Called as the first step of the Activity being paused. This is always called before + * {@link Activity#onPause}. + */ + default void onActivityPrePaused(@NonNull Activity activity) { + } + + /** + * Called when the Activity calls {@link Activity#onPause super.onPause()}. + */ void onActivityPaused(@NonNull Activity activity); + + /** + * Called as the last step of the Activity being paused. This is always called after + * {@link Activity#onPause}. + */ + default void onActivityPostPaused(@NonNull Activity activity) { + } + + /** + * Called as the first step of the Activity being stopped. This is always called before + * {@link Activity#onStop}. + */ + default void onActivityPreStopped(@NonNull Activity activity) { + } + + /** + * Called when the Activity calls {@link Activity#onStop super.onStop()}. + */ void onActivityStopped(@NonNull Activity activity); + + /** + * Called as the last step of the Activity being stopped. This is always called after + * {@link Activity#onStop}. + */ + default void onActivityPostStopped(@NonNull Activity activity) { + } + + /** + * Called as the first step of the Activity saving its instance state. This is always + * called before {@link Activity#onSaveInstanceState}. + */ + default void onActivityPreSaveInstanceState(@NonNull Activity activity, + @NonNull Bundle outState) { + } + + /** + * Called when the Activity calls + * {@link Activity#onSaveInstanceState super.onSaveInstanceState()}. + */ void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState); + + /** + * Called as the last step of the Activity saving its instance state. This is always + * called after{@link Activity#onSaveInstanceState}. + */ + default void onActivityPostSaveInstanceState(@NonNull Activity activity, + @NonNull Bundle outState) { + } + + /** + * Called as the first step of the Activity being destroyed. This is always called before + * {@link Activity#onDestroy}. + */ + default void onActivityPreDestroyed(@NonNull Activity activity) { + } + + /** + * Called when the Activity calls {@link Activity#onDestroy super.onDestroy()}. + */ void onActivityDestroyed(@NonNull Activity activity); + + /** + * Called as the last step of the Activity being destroyed. This is always called after + * {@link Activity#onDestroy}. + */ + default void onActivityPostDestroyed(@NonNull Activity activity) { + } } /** @@ -221,6 +352,18 @@ public class Application extends ContextWrapper implements ComponentCallbacks2 { mLoadedApk = ContextImpl.getImpl(context).mPackageInfo; } + @UnsupportedAppUsage + /* package */ void dispatchActivityPreCreated(@NonNull Activity activity, + @Nullable Bundle savedInstanceState) { + Object[] callbacks = collectActivityLifecycleCallbacks(); + if (callbacks != null) { + for (int i = 0; i < callbacks.length; i++) { + ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPreCreated(activity, + savedInstanceState); + } + } + } + @UnsupportedAppUsage /* package */ void dispatchActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) { @@ -233,6 +376,28 @@ public class Application extends ContextWrapper implements ComponentCallbacks2 { } } + @UnsupportedAppUsage + /* package */ void dispatchActivityPostCreated(@NonNull Activity activity, + @Nullable Bundle savedInstanceState) { + Object[] callbacks = collectActivityLifecycleCallbacks(); + if (callbacks != null) { + for (int i = 0; i < callbacks.length; i++) { + ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPostCreated(activity, + savedInstanceState); + } + } + } + + @UnsupportedAppUsage + /* package */ void dispatchActivityPreStarted(@NonNull Activity activity) { + Object[] callbacks = collectActivityLifecycleCallbacks(); + if (callbacks != null) { + for (int i = 0; i < callbacks.length; i++) { + ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPreStarted(activity); + } + } + } + @UnsupportedAppUsage /* package */ void dispatchActivityStarted(@NonNull Activity activity) { Object[] callbacks = collectActivityLifecycleCallbacks(); @@ -243,6 +408,26 @@ public class Application extends ContextWrapper implements ComponentCallbacks2 { } } + @UnsupportedAppUsage + /* package */ void dispatchActivityPostStarted(@NonNull Activity activity) { + Object[] callbacks = collectActivityLifecycleCallbacks(); + if (callbacks != null) { + for (int i = 0; i < callbacks.length; i++) { + ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPostStarted(activity); + } + } + } + + @UnsupportedAppUsage + /* package */ void dispatchActivityPreResumed(@NonNull Activity activity) { + Object[] callbacks = collectActivityLifecycleCallbacks(); + if (callbacks != null) { + for (int i = 0; i < callbacks.length; i++) { + ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPreResumed(activity); + } + } + } + @UnsupportedAppUsage /* package */ void dispatchActivityResumed(@NonNull Activity activity) { Object[] callbacks = collectActivityLifecycleCallbacks(); @@ -253,6 +438,26 @@ public class Application extends ContextWrapper implements ComponentCallbacks2 { } } + @UnsupportedAppUsage + /* package */ void dispatchActivityPostResumed(@NonNull Activity activity) { + Object[] callbacks = collectActivityLifecycleCallbacks(); + if (callbacks != null) { + for (int i = 0; i < callbacks.length; i++) { + ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPostResumed(activity); + } + } + } + + @UnsupportedAppUsage + /* package */ void dispatchActivityPrePaused(@NonNull Activity activity) { + Object[] callbacks = collectActivityLifecycleCallbacks(); + if (callbacks != null) { + for (int i = 0; i < callbacks.length; i++) { + ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPrePaused(activity); + } + } + } + @UnsupportedAppUsage /* package */ void dispatchActivityPaused(@NonNull Activity activity) { Object[] callbacks = collectActivityLifecycleCallbacks(); @@ -263,6 +468,26 @@ public class Application extends ContextWrapper implements ComponentCallbacks2 { } } + @UnsupportedAppUsage + /* package */ void dispatchActivityPostPaused(@NonNull Activity activity) { + Object[] callbacks = collectActivityLifecycleCallbacks(); + if (callbacks != null) { + for (int i = 0; i < callbacks.length; i++) { + ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPostPaused(activity); + } + } + } + + @UnsupportedAppUsage + /* package */ void dispatchActivityPreStopped(@NonNull Activity activity) { + Object[] callbacks = collectActivityLifecycleCallbacks(); + if (callbacks != null) { + for (int i = 0; i < callbacks.length; i++) { + ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPreStopped(activity); + } + } + } + @UnsupportedAppUsage /* package */ void dispatchActivityStopped(@NonNull Activity activity) { Object[] callbacks = collectActivityLifecycleCallbacks(); @@ -273,6 +498,28 @@ public class Application extends ContextWrapper implements ComponentCallbacks2 { } } + @UnsupportedAppUsage + /* package */ void dispatchActivityPostStopped(@NonNull Activity activity) { + Object[] callbacks = collectActivityLifecycleCallbacks(); + if (callbacks != null) { + for (int i = 0; i < callbacks.length; i++) { + ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPostStopped(activity); + } + } + } + + @UnsupportedAppUsage + /* package */ void dispatchActivityPreSaveInstanceState(@NonNull Activity activity, + @NonNull Bundle outState) { + Object[] callbacks = collectActivityLifecycleCallbacks(); + if (callbacks != null) { + for (int i = 0; i < callbacks.length; i++) { + ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPreSaveInstanceState( + activity, outState); + } + } + } + @UnsupportedAppUsage /* package */ void dispatchActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) { @@ -285,6 +532,28 @@ public class Application extends ContextWrapper implements ComponentCallbacks2 { } } + @UnsupportedAppUsage + /* package */ void dispatchActivityPostSaveInstanceState(@NonNull Activity activity, + @NonNull Bundle outState) { + Object[] callbacks = collectActivityLifecycleCallbacks(); + if (callbacks != null) { + for (int i = 0; i < callbacks.length; i++) { + ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPostSaveInstanceState( + activity, outState); + } + } + } + + @UnsupportedAppUsage + /* package */ void dispatchActivityPreDestroyed(@NonNull Activity activity) { + Object[] callbacks = collectActivityLifecycleCallbacks(); + if (callbacks != null) { + for (int i = 0; i < callbacks.length; i++) { + ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPreDestroyed(activity); + } + } + } + @UnsupportedAppUsage /* package */ void dispatchActivityDestroyed(@NonNull Activity activity) { Object[] callbacks = collectActivityLifecycleCallbacks(); @@ -295,6 +564,16 @@ public class Application extends ContextWrapper implements ComponentCallbacks2 { } } + @UnsupportedAppUsage + /* package */ void dispatchActivityPostDestroyed(@NonNull Activity activity) { + Object[] callbacks = collectActivityLifecycleCallbacks(); + if (callbacks != null) { + for (int i = 0; i < callbacks.length; i++) { + ((ActivityLifecycleCallbacks) callbacks[i]).onActivityPostDestroyed(activity); + } + } + } + private Object[] collectComponentCallbacks() { Object[] callbacks = null; synchronized (mComponentCallbacks) {