What is the correct order of calling superclass methods in onPause, onStop and onDestroy methods? and why?

I was just browsing the Android developer site, updating in the Life activity cycle, and in each code example there is a comment next to the methods of the superclass that says: "Always call the superclass method first."

Although this makes sense in the half-cycle of creation: onCreate, onStart, and onResume, I'm a little confused as to what is the correct procedure in the half-cycle of destruction: onPause, onStop, onDestroy.

First, destroying instance-specific resources before destroying the resources of the superclass, which depend on the specific resources of the instance, makes sense, and not vice versa. But the comments say the opposite. What am I missing?

Change Since people seem to be confused about intention in the question, what I want to know is right from the following: AND WHY?

1.Google offers

@Override protected void onStop() { super.onStop(); // Always call the superclass method first //my implementation here } 

2. Another way

  @Override protected void onStop() { //my implementation here super.onStop(); } 
+64
java android android-lifecycle
Sep 16 '13 at 6:17
source share
7 answers

Destroying instance-specific resources before destroying superclass resources that depend on specific instance resources makes sense, and not vice versa. But in the comments otherwise. What am I missing?

In my opinion: not a single thing.

This answer from Mark (aka CommonsWare on SO) sheds light on the problem: Link - Should a call to a superclass method be the first statement? . But then you can see the following comment left after his answer:

But why does the white paper say, “Always call the superclass method first” in onPause ()?

Return to the square. Well, look at it from a different angle. We know that the Java language specification does not indicate the order in which the super.overridenMethod() call should be placed (or if the call should be placed at all).

In the case of the Activity class, forced calls to super.overridenMethod() are also super.overridenMethod() :

 if (!mCalled) { throw new SuperNotCalledException( "Activity " + mComponent.toShortString() + " did not call through to super.onStop()"); } 

mCalled set to true in Activity.onStop() .

Now the only detail that needs to be discussed is ordering.

I also know that both work

Sure. Look at the body of the method for Activity.onPause ():

 protected void onPause() { if (DEBUG_LIFECYCLE) Slog.v(TAG, "onPause " + this); // This is to invoke // Application.ActivityLifecyleCallbacks.onActivityPaused(Activity) getApplication().dispatchActivityPaused(this); // The flag to enforce calling of this method mCalled = true; } 

Whichever way you run the super.onPause() call, everything will be fine. Activity.onStop () has the body of a similar method. But look at Activity.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); } 

Here, the ordering may matter depending on how your activity is configured, and whether the call to super.onDestroy() interfere with the following code.

As a final word, the Always call the superclass method first statement does not seem to have much evidence to support it. What's worse (for approval) is that the following code was derived from android.app.ListActivity :

 public class ListActivity extends Activity { .... @Override protected void onDestroy() { mHandler.removeCallbacks(mRequestFocus); super.onDestroy(); } .... } 

And, from the sample LunarLander application included in android sdk:

 public class LunarLander extends Activity { .... @Override protected void onPause() { mLunarView.getThread().pause(); // pause game when Activity pauses super.onPause(); } .... } 

Summary and noteworthy:

User Philip Sheard . Provides a scenario in which the call to super.onPause() should be deferred if the Activity starts using startActivityForResult(Intent) . Setting the result using setResult(...) after super.onPause() will not work. He later clarifies this in the comments on his answer.

Sherif elKhatib user : explains why starting a superclass initializes its resources first and destroys its resources. The latter follows from the logic:

Consider the library that you downloaded, which has a LocationActivity that contains the getLocation () function that provides the location. Most likely, this activity will have to initialize its materials in onCreate (), which will force you to call super.onCreate first . You are already doing 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 will be somewhat possible that getLocation will return a null value after this call, since the LocationActivity implementation will invalidate the location value in onDestroy. The idea is that you will not blame him if that happens. So you would call super.onDestroy at the end after you finish your own onDestroy.

He further indicates: if the child class is isolated (in terms of resource dependency) from the parent class, calls to super.X() should not adhere to any order specification.

See his answer on this page for a script in which the placement of a call to super.onDestroy() affects program logic.

From Mark's answer :

The methods that you override, which are part of creating the components (onCreate (), onStart (), onResume (), etc.), you should connect to the superclass as the first statement to make sure that Android has a chance to do before try to do something that depends on the work done.

The methods that you override are part of the destruction component (onPause (), onStop (), onDestroy (), etc.), you must do your work and binding to the superclass first and foremost. . What if Android cleans up what your work depends on, you will first do your job.

Methods that return something other than void (onCreateOptionsMenu (), etc.) sometimes get attached to the superclass in the return statement, assuming that you are not specifically something that is necessary to force the return value.

Everything else - for example, onActivityResult () - is up to you, in general. I lean toward the superclass as the first, but if you don't run into problems, the chain should be fine later.

Bob Cairns from this thread :

This is a good template [(the template that Mark offers above)], but I found some exceptions. For example, the theme that I wanted to apply to my PreferenceActivity function did not take effect unless I put it in front of the onCreate () superclass.

User Steve Benett also pays attention to this:

I know only one situation when the time of a super call is necessary. If you want to change the default behavior of a theme or display, etc. in onCreate, you must do this before calling super to see the effect . Otherwise, AFAIK there is no difference in which you call it.

User Sunil Mishra confirms that order (most likely) does not matter when invoking methods of the Activity class. He also claims that calling superclass methods is first considered best practice . However, I could not confirm this.

User LOG_TAG . Explains why the call to the superclass constructor should be in front of everything else. In my opinion, this explanation does not add to the question asked.

Final note : trust, but verify. Most of the answers on this page follow this approach to ensure that the Always call the superclass method first has logical support. As it turned out, this is not so; at least not in the case of the Activity class. Typically, you need to read the source code of a superclass to determine if the ordering requirement is for super-methods.

+74
Sep 18 '13 at 14:09
source share

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) { //i want to go to a certain activity when there are no other activities startActivity(new Intent(this, GoodBye.class)); } } 

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.

+10
Sep 18 '13 at 11:54 on
source share

BOTH are the right IMO

According to the docs

Derived classes should move on to implementing the superclass of this method. If they do not, an exception will be thrown.

Super method should always be called when the documentation explicitly says so.

However, you can choose when to call the super method.

Looking at the source onPause

 protected void onPause() { getApplication().dispatchActivityPaused(this); mCalled = true; } 

Therefore, regardless of before or after its call. You must be good.

But for best practice, you should first call it.

I recommend it mainly as a defense mechanism: if there is an exception, then the Super instance method has already been called.

Also, placing these calls on the first line will help to avoid future errors, such as deleting code in a method and accidentally deleting a call to a superclass.

+1
Sep 16 '13 at 6:40
source share

Most importantly, keep in mind that super.onPause() implicitly calls setResult(Activity.RESULT_CANCELED) . But setResult can only be called once, and all subsequent calls are ignored. Therefore, if you want to return any result to parent activity, you must call setResult yourself, before , you call super.onPause() . As far as I know, this is the biggest catch.

+1
Sep 18 '13 at 15:17
source share

You say that Google offers Method 1, but Dianne Hackborn, a well-known Android infrastructure engineer, suggests otherwise referring to the link in the Google Forum .

For an intuitive sense, call the superclass the last when the instance is destroyed in onPause, onStop and onDestroy strong> and first when it creates an instance using the onCreate, onResume and onStart methods .

+1
Sep 19 '13 at 11:26
source share

Super callbacks need the Activity object to be in the correct state for the system.

Let's say you start your business and the onCreate system is called by the system. Now you can override it and, for example, load the layout. But for system flow, you need to call super so that the system can continue the standard procedure. This is why an exception will be thrown if you do not name it.

This happens regardless of your implementation in onCreate. This is system only. If there wasn’t ANR, you could have an infinite loop in any callback, and activity would be caught in that. That way, the system knows when the callback was completed, and then calls the next one.

I know only one situation when time for super calls is necessary. If you want to change the default behavior of a theme or display, etc. In onCreate, you need to do this before you call super to see the effect. Otherwise, AFAIK will not make any difference when you call it.

But for the system to do what it is best to put super on the first line of the callback, followed by your code if you have no good reason to break it.

0
Sep 16 '13 at 10:06 on
source share

From a java point of view, there is some solution for this confusion:

Why should this () and super () be the first statement in the constructor?

The constructor of the parent class must be called before the constructor of the subclass. This ensures that if you call any methods of the parent class in your constructor, the parent class is already configured correctly.

, , , , inline, , , :

 public MySubClassB extends MyClass { public MySubClassB(Object[] myArray) { super(myArray); } } 

, :

 public MySubClassB extends MyClass { public MySubClassB(Object[] myArray) { someMethodOnSuper(); //ERROR super not yet constructed super(myArray); } } 

, ! , Java- "" , , -

, , . Java Object, -, . () . , , : Object → Parent → Child → ChildOfChild → SoOnSoForth

(1) , super - , . , "super (someMethodInSuper())"; . , .

(2) The compiler seems to implement another check, which in itself is sufficient to prevent this problem. The message "cannot reference xxx before the supertype constructor was created." Therefore, verifying that super is the first statement is not required

Please go through http://valjok.blogspot.in/2012/09/super-constructor-must-be-first.html

0
Sep 18 '13 at 12:05
source share



All Articles