Since (you say), it makes sense to call super onCreate first: think about it.
When I want to create, My super creates my resources> I create my resources.
Forward: (stack type)
When I want to destroy, I destroy my resources> My super destroys its resources.
In this sense, it applies to any function (onCreate / onDestroy, onResume / onPause, onStart / onStop). Naturally, onCreate will create resources, and onDestroy will free these resources. By the way, the same proof applies to other pairs.
Consider the library that you downloaded, which has a LocationActivity that contains the getLocation () function that provides the location. Most likely, this action will have to initialize its stuff in onCreate (), which will force you to call super.onCreate first. You already do this because you feel it makes sense. Now, in your onDestroy, you decide you want to save the location somewhere in SharedPreferences. If you call super.onDestroy first, it is somewhat possible that getLocation will return a null value after this call, because the LocationActivity implementation resets the location value to onDestroy. The idea is that you will not blame her if that happens. So you would call super.onDestroy at the end after you are done with your own onDestroy. Hope this changes a bit.
If this makes sense, consider that at any time we have an activity that adheres to the above concept. If I want to expand this activity, I will probably feel the same and follow the same order because of the same exact argument.
By induction, any activity should do the same. Here is a good abstract class for activities forced to follow these rules:
package mobi.sherif.base; import android.app.Activity; import android.os.Bundle; public abstract class BaseActivity extends Activity { protected abstract void doCreate(Bundle savedInstanceState); protected abstract void doDestroy(); protected abstract void doResume(); protected abstract void doPause(); protected abstract void doStart(); protected abstract void doStop(); protected abstract void doSaveInstanceState(Bundle outState); @Override protected final void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); doCreate(savedInstanceState); } @Override protected final void onDestroy() { doDestroy(); super.onDestroy(); } @Override protected final void onResume() { super.onResume(); doResume(); } @Override protected final void onPause() { doPause(); super.onPause(); } @Override protected final void onStop() { doStop(); super.onStop(); } @Override protected final void onStart() { super.onStart(); doStart(); } @Override protected final void onSaveInstanceState(Bundle outState) { doSaveInstanceState(outState); super.onSaveInstanceState(outState); } }
Finally, what if your activity called AnudeepBullaActivity extends BaseActivity and later, I want to create a SherifElKhatibActivity that extends your activity? In what order should I call super.do functions? It is ultimately the same.
Regarding your question:
I think Google’s intention is to tell us: please call super no matter where. As a rule, of course, call at the beginning. Google, of course, has the most vibrant engineers and developers, so they probably did a good job isolating their super-calls and not interfering with the child’s calls.
I did a little work, and probably not easy (since it’s Google, we’re trying to prove that it’s not) in order to create an activity that could work just because When you call super.
Why?
Everything that is done in these functions is really private to the Activity class and will never lead to a conflict with your subclass. For example (onDestroy)
protected void onDestroy() { if (DEBUG_LIFECYCLE) Slog.v(TAG, "onDestroy " + this); mCalled = true; // dismiss any dialogs we are managing. if (mManagedDialogs != null) { final int numDialogs = mManagedDialogs.size(); for (int i = 0; i < numDialogs; i++) { final ManagedDialog md = mManagedDialogs.valueAt(i); if (md.mDialog.isShowing()) { md.mDialog.dismiss(); } } mManagedDialogs = null; } // close any cursors we are managing. synchronized (mManagedCursors) { int numCursors = mManagedCursors.size(); for (int i = 0; i < numCursors; i++) { ManagedCursor c = mManagedCursors.get(i); if (c != null) { c.mCursor.close(); } } mManagedCursors.clear(); } // Close any open search dialog if (mSearchManager != null) { mSearchManager.stopSearch(); } getApplication().dispatchActivityDestroyed(this); }
mManagedCursors and mManagedDialogs and mSearchManager are all private fields. And none of the public / protected api will be affected by what is done here.
However, in API 14, dispatchActivityDestroyed was added to send onActivityDestroyed to ActivityLifecycleCallbacks registered in your application. Therefore, any code that will depend on some logic in ActivityLifecycleCallbacks will have a different result based on when you call super. For example:
Create an application class that counts the number of ongoing activities:
package mobi.shush; import android.app.Activity; import android.app.Application; import android.app.Application.ActivityLifecycleCallbacks; import android.os.Bundle; public class SherifApplication extends Application implements ActivityLifecycleCallbacks { @Override public void onCreate() { super.onCreate(); registerActivityLifecycleCallbacks(this); } public int getCount() { return count; } int count = 0; @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { count++; } @Override public void onActivityDestroyed(Activity activity) { count--; } @Override public void onActivityPaused(Activity activity) {} @Override public void onActivityResumed(Activity activity) {} @Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) {} @Override public void onActivityStarted(Activity activity) {} @Override public void onActivityStopped(Activity activity) {} }
It may not make sense or is not good practice, but it is just to prove the point (one could find a more real situation). Create a MainActivity that is supposed to transition to GoodBye when it is completed, and when it will be the last action:
@Override protected void onDestroy() { super.onDestroy(); if(((SherifApplication) getApplication()).getCount() == 0) {
If you call super.onDestroy at the beginning of your onDestroy, GoodBye will run. If you call super.onDestroy at the end of your onDestroy, the GoodBye action will not be triggered.
Of course, again, this is not an optimal example. However, this shows that Google is a little messed up. Any of the other variables will not affect the behavior of your application. However, adding this dispatch to onDestroy made super somehow interfere with your subclass.
I say that they were confused for another reason. They not only (until api 14) dealt only with super-calls, which is final and / or private, but also called different internal functions (private) that actually sent onPause functions ...
For example, the performStop function is a function that in turn calls the onStop function:
final void performStop() { if (mLoadersStarted) { mLoadersStarted = false; if (mLoaderManager != null) { if (!mChangingConfigurations) { mLoaderManager.doStop(); } else { mLoaderManager.doRetain(); } } } if (!mStopped) { if (mWindow != null) { mWindow.closeAllPanels(); } if (mToken != null && mParent == null) { WindowManagerGlobal.getInstance().setStoppedState(mToken, true); } mFragments.dispatchStop(); mCalled = false; mInstrumentation.callActivityOnStop(this); if (!mCalled) { throw new SuperNotCalledException( "Activity " + mComponent.toShortString() + " did not call through to super.onStop()"); } synchronized (mManagedCursors) { final int N = mManagedCursors.size(); for (int i=0; i<N; i++) { ManagedCursor mc = mManagedCursors.get(i); if (!mc.mReleased) { mc.mCursor.deactivate(); mc.mReleased = true; } } } mStopped = true; } mResumed = false; }
Note that they call Activity onStop somewhere in this function. Therefore, they could also put all the code (included in super.onStop) before or after calling onStop, and then simply notify subclasses of onStop using empty onStop superfunctions and not even adding a SuperNotCalledException or checking it.
To do this, if they called this dispatch to ActivityLifeCycle in executeDestroy, and did not call it at the end of super.onDestroy, our activity behavior would be the same, regardless of when we call super.
In any case, this is the first thing they do (a little wrong), and this is only in API 14.