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

JavaAndroidAndroid Lifecycle

Java Problem Overview


I was just going through the Android Developer Site, refreshing on the Activity Life cycle, and in each code example, there is a comment beside the super class methods that says "Always call the superclass method first".

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

Destroying the instance specific resources first, before destroying superclass resources that the instance specific resources may depend upon makes sense, not the other way round.But the comments suggest otherwise. What am I missing?

Edit: Since people seem to be getting confused as to the intent in the question, what I want to know is which of the following is correct? AND WHY ?

1.Google suggests

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

2.The other way

    @Override
    protected void onStop() {
       //my implementation here

       super.onStop();  
    }

Java Solutions


Solution 1 - Java

> Destroying the instance specific resources first, before destroying > superclass resources that the instance specific resources may depend > upon makes sense, not the other way round. But the comments suggest > otherwise. What am I missing?

In my opinion: not a single thing.

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

>But why official doc says: "Always call the superclass method first" in onPause()?

Back to square one. Okay, let's look at this from another angle. We know that Java Language Specification does not specify an order in which the call to super.overridenMethod() must be placed (or if the call must be placed at all).

In case of class Activity, super.overridenMethod() calls are required and enforced:

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

mCalled is set to true in Activity.onStop().

Now, the only detail left to debate on is the ordering.

I also know that both work

Sure. Look at the method body 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 sandwich the call to super.onPause(), you'll be ok. Activity.onStop() has a similar method body. But take a 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 could possibly matter depending on how your activity is setup, and whether calling super.onDestroy() would interfere with the code that follows.

As a final word, the statement Always call the superclass method first doesn't seem to have much evidence to back it up. What's worse (for the statement) is that the following code has been taken from android.app.ListActivity:

public class ListActivity extends Activity {

    ....

    @Override
    protected void onDestroy() {
        mHandler.removeCallbacks(mRequestFocus);
        super.onDestroy();
    }
    ....    
}

And, from LunarLander sample 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 worthy mentions:

User Philip Sheard : Provides a scenario where a call to super.onPause() must be delayed in case of an Activity started using startActivityForResult(Intent). Setting the result using setResult(...) after super.onPause() will not work. He later clarifies on this in the comments to his answer.

User Sherif elKhatib : Explains why letting superclass initialize its resources first and destroy its resources last follows from logic:

> Let us consider a library you downloaded which has a LocationActivity > that contains a getLocation() function that provides the location. > Most probably, this activity will need to initialize its stuff in the > onCreate() which will force you to call the super.onCreate first. You > already do that because you feel it makes sense. Now, in your > onDestroy, you decide you want to save the Location somewhere in the > SharedPreferences. If you call super.onDestroy first, it is to a > certain extent possible that getLocation will return a null value > after this call because the implementation of LocationActivity > nullifies the location value in the onDestroy. The idea is that you > wouldn't blame it if this happens. Therefore, you would call > super.onDestroy at the end after you're done with your own onDestroy.

He goes on to point out: if a child class is suitably isolated (in terms of resource dependency) from the parent class, the super.X() calls need not adhere to any order specification.

See his answer on this page to read through a scenario where placement of super.onDestroy() call does affect the program logic.

From an answer by Mark:

> Methods you override that are part of component creation (onCreate(), > onStart(), onResume(), etc.), you should chain to the superclass as > the first statement, to ensure that Android has its chance to do its > work before you attempt to do something that relies upon that work > having been done.

> Methods you override that are part of component > destruction (onPause(), onStop(), onDestroy(), etc.), you should do > your work first and chain to the superclass as the last thing. That > way, in case Android cleans up something that your work depends upon, > you will have done your work first.

> Methods that return something > other than void (onCreateOptionsMenu(), etc.), sometimes you chain to > the superclass in the return statement, assuming that you are not > specifically doing something that needs to force a particular return > value.

> Everything else -- such as onActivityResult() -- is up to you, > on the whole. I tend to chain to the superclass as the first thing, > but unless you are running into problems, chaining later should be > fine.

Bob Kerns from this thread:

> It's a good pattern [(the pattern that Mark suggests above)], but I've found some exceptions. For example, > the theme I wanted to apply to my PreferenceActivity wouldn't take > effect unless I put it before the superclass's onCreate().

User Steve Benett also brings attention to this:

> I only know one situation, where the timing of the super call is > necessary. If you wanna alter the standard behavior of the theme or > the display and such in onCreate, you have to do it before you call > super to see an effect. Otherwise AFAIK there is no difference at > which time you call it.

User Sunil Mishra confirms that order (most likely) does not play a role when calling Activity class' methods. He also claims that calling superclass methods first is considered a best practice. However, I could not corroborate this.

User LOG_TAG : Explains why a call to superclass constructor needs to be the before everything else. In my opinion, this explanation does not add to the question being asked.

End note: Trust, but verify. Most of the answers on this page follow this approach to see if the statement Always call the superclass method first has logical backing. As it turns out, it does not; at least, not in the case of class Activity . Generally, one should read through the superclass' source code to determine if ordering calls to super's methods is a requirement.

Solution 2 - Java

Since (you say) it makes sense to call super onCreate first: Think about it.

When I want to create, My super creates its resources > I create my resources.

Inversely: (sort of a stack)

When I want to destroy, I destroy my resources > My super destroys his resources.


In this sense, it applies to any couple of functions (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 the other couples.

Let us consider a library you downloaded which has a LocationActivity that contains a getLocation() function that provides the location. Most probably, this activity will need to initialize its stuff in the onCreate() which will force you to call the super.onCreate first. You already do that because you feel it makes sense. Now, in your onDestroy, you decide you want to save the Location somewhere in the SharedPreferences. If you call super.onDestroy first, it is to a certain extent possible that getLocation will return a null value after this call because the implementation of LocationActivity nullifies the location value in the onDestroy. The idea is that you wouldn't blame it if this happens. Therefore, you would call super.onDestroy at the end after you're done with your own onDestroy. I hope this makes a bit sense.

If the above makes sense, consider that at any moment we have an activity that abides by the above concept. If I want to extend this activity, I will probably feel the same way and follow the same ordering because of the same exact argument.

By induction, any activity should do the same thing. Here is a good abstract class for an activity 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 on, I want to create SherifElKhatibActivity that extends your activity? In what order should i call the super.do functions? It is ultimately the same thing.


As for your question:

I think that Google's intention is to tell us: Please call the super no matter where. As a general practice of course, call it in the beginning. Google of course has the brightest engineers and developers so they probably done a good job isolating their super calls and not interfering in the child calls.

I tried a bit and it is probably not easy (since it is Google we are trying to prove wrong) to create an activity that would crash simple because of When is super being called.

Why?

Anything done in these functions is really private to the Activity class and would never cause any 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 dispatch an onActivityDestroyed to the ActivityLifecycleCallbacks registered to your Application. Therefore, any code that would depend on some logic in your ActivityLifecycleCallbacks will have a different outcome based on when you are calling the super. For example:

Create an Application Class that counts the number of currently running 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) {}
}

The following might not make sense or is not that of a good practice but it is just to prove a point (One might find a more real situation). Create the MainActivity that supposedly goes to GoodBye activity when it is finished and when it is the last activity:

@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 in the beginning of your onDestroy, the GoodBye activity will be launched. If you call super.onDestroy at the end of your onDestroy, the GoodBye activity will not be launched.

Of course, again, this is not the optimal example. However this shows that Google messed up a bit here. Any of the other variables would have not affected your app's behavior. However adding these dispatch to the onDestroy caused the super to somehow interfere with your subclass.

I say they messed for a different reason as well. Not only did they (before api 14) only touch in the super calls what is final and/or private, but they also called different internal functions (private) that really then dispatched the onPause... functions.

For example, performStop function is the function called 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;
}

Notice that they call the Activity's onStop somewhere in this function. Therefore, they might have as well put all the code (included in super.onStop) before or after the call to onStop and then just notify subclasses about the onStop using empty onStop super functions and without even adding the SuperNotCalledException or checking for this called.

For this, if they called this dispatch to the ActivityLifeCycle in the performDestroy instead of calling it in the end of super.onDestroy, our activity's behavior would have been the same regardless of when we did call the super.

Anyway this is the first thing they do (a bit wrong) and it is only in API 14.

Solution 3 - Java

You say that Google suggests method 1, however Dianne Hackborn, a well known Android framework engineer suggest otherwise see Google Forum Link.

It makes intuitive sense to call the super class last when destroying an instance in the onPause, onStop and onDestroy methods and first when creating an instance with the methods of onCreate, onResume and onStart.

Solution 4 - Java

BOTH are correct IMO

According to the docs

>Derived classes must call through to the super class's implementation of this method. If they do not, an exception will be thrown.

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

You can however choose when to call the super method.

Looking at the source of onPause

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

Hence no matter before or after it is called. You should be good.

But for best practice, you should be calling it first.

I recommend it mostly as a protection mechanism: if there is an exception then the super instance method will already have been called.

Also putting these calls on the first line will help you avoid making mistakes in the future such as deleting code in the method and accidentally deleting the call to the super class.

Solution 5 - Java

From java perspective here is some solution for this confusion:

Why does this() and super() have to be the first statement in a constructor?

The parent class' constructor needs to be called before the subclass' constructor. This will ensure that if you call any methods on the parent class in your constructor, the parent class has already been set up correctly.

What you are trying to do, pass args to the super constructor is perfectly legal, you just need to construct those args inline as you are doing, or pass them in to your constructor and then pass them to super:

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

If the compiler did not enforce this you could do this:

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

It shows that actually, subfields have to be inilialized before the supreclass! Meantime, java requirement "defends" us from specializing the class by specializing what the super constructor argument

In cases where a parent class has a default constructor the call to super is inserted for you automatically by the compiler. Since every class in Java inherits from Object, objects constructor must be called somehow and it must be executed first. The automatic insertion of super() by the compiler allows this. Enforcing super to appear first, enforces that constructor bodies are executed in the correct order which would be: Object -> Parent -> Child -> ChildOfChild -> SoOnSoForth

(1) Checking that super is the first statement is not sufficient to prevent that problem. For example, you could put "super(someMethodInSuper());" in your constructor. This attempts to access a method in the superclass before it is constructed, even though super is the first statement.

(2) The compiler appears to implement a different check which is, by itself, sufficient to prevent this problem. The message is "cannot reference xxx before supertype constructor has been called". Therefore, checking that super is the first statement is not necessary

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

Solution 6 - Java

The most important thing to bear in mind is that super.onPause() implicitly calls setResult(Activity.RESULT_CANCELED). But setResult can only be called once, and all subsequent calls are ignored. So if you want to push any kind of result back to the parent activity, you have to call setResult yourself, before you call super.onPause(). That is the biggest gotcha, as far as I know.

Solution 7 - Java

The super of the callbacks is needed to put the Activity in the right state internally for the system.

Let's say you start your Activity and onCreate is invoked by the system. Now you can override it and e.g. load your layout. But in sake of the system flow you have to call super, that the system can continue with the standard procedure. That's why an exception will be thrown if you don't call it.

This happens independent of your implementation in onCreate. It's only importend for the system. If there would be no ANR you could have an endless loop in any callback and the Activity would be caught in that one. So, the system knows when the callback has been terminated and than calls the next one.

I only know one situation, where the timing of the super call is necessary. If you wanna alter the standard behavior of the theme or the display and such in onCreate, you have to do it before you call super to see an effect. Otherwise AFAIK there is no difference at which time you call it.

But to let the system do what it can best put the super in the first line of a callback followed by your code, if you don't have a good reason to break with it.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAnudeep BullaView Question on Stackoverflow
Solution 1 - JavaVikramView Answer on Stackoverflow
Solution 2 - JavaSherif elKhatibView Answer on Stackoverflow
Solution 3 - JavaNickTView Answer on Stackoverflow
Solution 4 - JavaSunil MishraView Answer on Stackoverflow
Solution 5 - JavaLOG_TAGView Answer on Stackoverflow
Solution 6 - JavaPhilip SheardView Answer on Stackoverflow
Solution 7 - JavaSteve BenettView Answer on Stackoverflow