It is quite revealing to monitor an activity's life cycle in Android. Here is some source code that you can use to monitor logcat and see how an activity behaves and various activity life cycle call backs happen.

satya - 8/19/2013 2:43:56 PM

Here is the code that you can use


public class MonitoredActivity extends Activity
{
   private String tag = null;
   MonitoredActivity(String intag) {tag = intag;}
   
   @Override
   protected void onCreate(Bundle savedInstanceState) {
      Log.d(tag,"onCreate.");
      super.onCreate(savedInstanceState);
   }
   @Override
   protected void onPause() {
      Log.d(tag,"onpause. I may be partially or fully invisible");
      super.onPause();
   }
   @Override
   protected void onStop() {
      Log.d(tag,"onstop. I am fully invisible");
      super.onStop();
   }
   @Override
   protected void onDestroy() {
      Log.d(tag,"ondestroy. about to be removed");
      super.onDestroy();
   }
   
   //Only called when an activity is restarted
   //without getting destroyed first. 
   //So this will be called when your activity is 
   //hidden and brought back such as going to to home
   //and coming back.
   //
   //onRestart also means, hence, UI is not disturbed
   //
   @Override
   protected void onRestart() {
      Log.d(tag,"onRestart. UI controls are there.");
      super.onRestart();
   }
   @Override
   protected void onStart() {
      Log.d(tag,"onStart. UI may be partially visible.");
      super.onStart();
   }
   @Override
   protected void onResume() {
      Log.d(tag,"onResume. UI fully visible.");
      super.onResume();
   }
   //Called between onStart and onResume
   @Override
   protected void onRestoreInstanceState(Bundle savedInstanceState) {
      Log.d(tag,"onRestoreInstanceState. You should restore state");
      super.onRestoreInstanceState(savedInstanceState);
   }

   //Called only when there is a configuration change
   //Called between onStop and onDestroy
   //You can return a local object pointer to 
   //retrieve it back through getConfigurationInstance.
   @Override
   public Object onRetainNonConfigurationInstance() {
      Log.d(tag,"onRetainNonConfigurationInstance.");
      return super.onRetainNonConfigurationInstance();
   }

   @Override
   protected void onSaveInstanceState(Bundle outState) {
      Log.d(tag,"onSaveInstanceState. You should load up the bundle");
      super.onSaveInstanceState(outState);
   }
   
   //This method is called when you disable a configuration 
   //change in the manifest file for this activity.
   //Instead the activity stays as is and this method is called.
   //
   @Override
   public void onConfigurationChanged(Configuration newConfig) {
      Log.d(tag,"onConfigurationChanged. No rotation occurs.");
      super.onConfigurationChanged(newConfig);
   }

}

/*
 * One possible order when screen flips
 * ***************************************
//Begining...
onCreate
onStart
onRestoreInstanceState
onResume


//configuration changed
onSaveInstanceState
onPause : partially visible ui
onStop: ui invisible
onRetainNonConfigurationInstance: an local objects you want to remeber
onDestroy

//Back to begining
 * 
 * onRestart and Some other observation
 * *****************************************
 * The sequence of calls will be different
 * for going to home and revisiting the activity.
 * 
 * 1. onRetart will be called instead of onCreate
 * 2. onStart will be called from onRestart
 * 3. See the activity diagram
 * 4. See satyakomatineni.com/item/3528
 * 
 */

satya - 8/19/2013 2:44:27 PM

Modify this code as you see fit as this is just a snapshot of when I was last working on it

Modify this code as you see fit as this is just a snapshot of when I was last working on it

satya - 8/19/2013 2:44:57 PM

Here is some theory and observations on life cycle of an activity

Here is some theory and observations on life cycle of an activity

satya - 1/19/2014 11:27:37 AM

A bit enahanced


public class MonitoredActivity extends Activity
{
   protected String tag = null;
   MonitoredActivity(String intag) {tag = intag;}
   
   @Override
   protected void onCreate(Bundle savedInstanceState) {
      Log.d(tag,"onCreate.");
      super.onCreate(savedInstanceState);
   }
   @Override
   protected void onPause() {
      Log.d(tag,"onpause. I may be partially or fully invisible");
      if (isFinishing() == true)
      {
         Log.d(tag,"The activity is closing by expectation. isFinishing() is true");
      }
      else
      {
         Log.d(tag,"The activity is closing by force or on a config change. isFinishing() is false");
      }
      super.onPause();
   }
   @Override
   protected void onStop() {
      Log.d(tag,"onstop. I am fully invisible");
      super.onStop();
   }
   @Override
   protected void onDestroy() {
      Log.d(tag,"ondestroy. about to be removed");
      if (isFinishing() == true)
      {
         Log.d(tag,"The activity is closing by expectation. isFinishing() is true, like on a back");
         releaseResources();
      }
      super.onDestroy();
   }
   
   //Only called when an activity is restarted
   //without getting destroyed first. 
   //So this will be called when your activity is 
   //hidden and brought back such as going to to home
   //and coming back.
   //
   //onRestart also means, hence, UI is not disturbed
   //
   @Override
   protected void onRestart() {
      Log.d(tag,"onRestart. UI controls are there.");
      super.onRestart();
   }
   @Override
   protected void onStart() {
      Log.d(tag,"onStart. UI may be partially visible.");
      super.onStart();
   }
   @Override
   protected void onResume() {
      Log.d(tag,"onResume. UI fully visible.");
      super.onResume();
   }
   //Called between onStart and onResume
   @Override
   protected void onRestoreInstanceState(Bundle savedInstanceState) {
      Log.d(tag,"onRestoreInstanceState. You should restore state");
      super.onRestoreInstanceState(savedInstanceState);
   }

   //Called only when there is a configuration change
   //Called between onStop and onDestroy
   //You can return a local object pointer to 
   //retrieve it back through getConfigurationInstance.
   @Override
   public Object onRetainNonConfigurationInstance() {
      Log.d(tag,"onRetainNonConfigurationInstance.");
      return super.onRetainNonConfigurationInstance();
   }

   @Override
   protected void onSaveInstanceState(Bundle outState) {
      Log.d(tag,"onSaveInstanceState. You should load up the bundle");
      super.onSaveInstanceState(outState);
   }
   
   //This method is called when you disable a configuration 
   //change in the manifest file for this activity.
   //Instead the activity stays as is and this method is called.
   //
   @Override
   public void onConfigurationChanged(Configuration newConfig) {
      Log.d(tag,"onConfigurationChanged. No rotation occurs.");
      super.onConfigurationChanged(newConfig);
   }

   //You should call this if an activity is 
   //known to be legitly closing.
   //ex:
   //   a) explicit finish
   //   b) implied finish such as back
   //
   //An activity may also close for
   //   a) a config change to reborn
   //   b) low memory process is getting terminated
   protected void releaseResources()
   {
      //default is nothing
      //override this method to do more if needed.
      Log.d(tag,"Release Resources called");
   }
   
   public void startTargetActivity(Class<? extends Activity> targetActivityClass)
   {
      Intent i = new Intent(this,targetActivityClass);
      startActivity(i);      
   }
}

/*
 * One possible order when screen flips
 * ***************************************
//Begining...
onCreate
onStart
onRestoreInstanceState
onResume


//configuration changed
onSaveInstanceState
onPause : partially visible ui
onStop: ui invisible
onRetainNonConfigurationInstance: an local objects you want to remeber
onDestroy

//Back to begining
 * 
 * onRestart and Some other observation
 * *****************************************
 * The sequence of calls will be different
 * for going to home and revisiting the activity.
 * 
 * 1. onRetart will be called instead of onCreate
 * 2. onStart will be called from onRestart
 * 3. See the activity diagram
 * 4. See satyakomatineni.com/item/3528
 * 
 */

satya - 2/12/2014 8:43:25 AM

Here is a quick picture from the link above

satya - 2/12/2014 8:43:47 AM

This is borrowed from the link

This is borrowed from the link

satya - 2/12/2014 9:59:16 AM

That link may be wrong. Use this one

That link may be wrong. Use this one

satya - 2/12/2014 10:00:41 AM

Android View state and onStart()

Android View state and onStart()

Search for: Android View state and onStart()

satya - 2/12/2014 12:18:51 PM

In Android View Hierarchy, onStart() and onStop()

In Android View Hierarchy, onStart() and onStop()

Search for: In Android View Hierarchy, onStart() and onStop()

satya - 2/12/2014 12:20:22 PM

Here is the same question put differently: SOF

Here is the same question put differently: SOF

satya - 2/12/2014 12:30:03 PM

Recollecting...

view hierarchies are established in onCreate() before the start and stop cycle as your activity gets shown and hidden.

So the view hierarchies are not destroyed in onStop() and they are available to onStart() as they were established by onCreate() and possibly altered in the process of progress.

If you were to load and establish layouts in onStart() it is a lot of unnecessary work as long all that needs to be done is to fix the state between stop and start.

however there may never be a need to do anything special in onStart() if you are not doing something in onStop()that needs to be undone.

satya - 2/12/2014 1:30:43 PM

Some key facts on onStart()

  1. It is much advisable that the layouts are not loaded here
  2. The view state is not restored by the time this method is called
  3. onRestoreInstanceState() is called after onStart()
  4. onResume() is guranteed to be called after onStart
  5. This can be called either after onCreate() or onRestore(). So you cannot make assumptions about what kind of a state a view is in.
  6. This method is the start of the visible life cycle
  7. The activity is either invisible or partially visible at the time of this call
  8. It is only after the next method onResume() the activity is fully visible
  9. Followed by onStart() you may have multiple pause, resume cycles. You can therefore write code there if you want some optimization that is outside of that loop.
  10. It is generally the case that the view hierarchy exists prior to onstart
  11. the onstop will not destroy the view hierarchy

satya - 2/12/2014 1:33:44 PM

Finagling opportunities....

Because onStop() doesn't destroy the view state, you may have an opportunity to detect the onRestart() vs onCreate() and may set the state of the activity so that subsequent methods can run some optimizations.

However onResume() may be in a better state to recognize as it is the last loop in the life cycle.

satya - 2/12/2014 2:17:23 PM

Notice that a number of these callbacks don't have the bundle with them!

Notice that a number of these callbacks don't have the bundle with them!

satya - 2/12/2014 2:17:48 PM

onPause

When activity B is launched in front of activity A, this callback will be invoked on A. B will not be created until A's onPause() returns, so be sure to not do anything lengthy here.

satya - 2/12/2014 2:19:02 PM

another important note onPause

This callback is mostly used for saving any persistent state the activity is editing, to present a "edit in place" model to the user and making sure nothing is lost if there are not enough resources to start the new activity without first killing this one. This is also a good place to do things like stop animations and other things that consume a noticeable amount of CPU in order to make the switch to the next activity as fast as possible, or to close resources that are exclusive access such as the camera.

satya - 2/12/2014 2:20:46 PM

Saving persistent data vs instance state data: onPause

In situations where the system needs more memory it may kill paused processes to reclaim resources. Because of this, you should be sure that all of your state is saved by the time you return from this function. In general onSaveInstanceState(Bundle) is used to save per-instance state in the activity and this method is used to store global persistent data (in content providers, files, etc.)

satya - 2/12/2014 2:21:21 PM

Because onPause() does not have a bundle where do you save?

use external files etc...as stated above.

satya - 2/12/2014 2:22:08 PM

So whatever you do in onPause, you need to reverse it in onResume

So whatever you do in onPause, you need to reverse it in onResume

satya - 2/12/2014 4:01:58 PM

onSaveInstanceState() timing

If called, this method will occur before onStop(). There are no guarantees about whether it will occur before or after onPause().

satya - 2/12/2014 4:07:39 PM

onSaveInstanceState() not called

  1. when going back, because no need to restore
  2. when going home, because user may return and view is kept alive
  3. another activity hiding it. Same as home case.

satya - 2/12/2014 4:08:11 PM

onSaveInstanceState() called

  1. Configuration change
  2. activity is killed due to low memory conditions

satya - 2/12/2014 4:56:13 PM

What is instance state of an activity?

It is the transient state that lives and dies with an activity. It is the state that the system wants to bring back if the activity is to be restarted either due to a configuration change or other automatic needs as perceived by android.

It is the state of the activity that may not be restored if activity were to be started a new. So there is no expectation that one needs to start off where one leaves off...in that case the expectation is that the state needs to be persisted beyond the life time of the activity and hence must be stored persistently in a database or a file or on the network.

So when you store something in the instance state, it can be lost in some circumstances. Say when you go back. Then the entire instance of the activity is gone including what you may have typed. Or if the activity is killed due to low memory conditions and system didn't have an opportunity to call onRestoreInstanceState.

satya - 2/12/2014 4:59:01 PM

What is then persistent state of an activity?

When you don't want to loose any data when activity comes and goes including on a back button and in all circumstances or when you want the activity to start always, (like on reinstalls, or device restarts), then you may want to use onPause() to store the data to a flat file in a persistent manner. thats why it is called persistence state. Only onpause() is expected to be able to do this. Being on the main thread there is a limited time that you can cram into this.

satya - 2/12/2014 5:03:29 PM

what do I loose if I use instance state?

You will understand that the back button will reset the state of your activity, under low level and some other memory conditions you may start the activity in an initial state

on the other hand you preserve your state across configuration changes, you preserve it even under low level memory conditions most of the time.

Because the instance state methods make this saving experience pretty easy along with the natural state of the views.

By the way even if you were to go with the persistence state, usually that does not include various view states and you have to manually restore those states yourself. (of course only if needed)

satya - 2/12/2014 5:05:13 PM

is there a hybrid approach?

it is possible to discover in onPause if the activity is going to restart, and in which case you can rely on the restore methods, and if not, and if needed use the persistence save then if the activity is actually finishing using the isFinishing method.

satya - 2/12/2014 5:07:55 PM

onStop timing: may never be called

Note that this method may never be called, in low memory situations where the system does not have enough memory to keep your activity's process running after its onPause() method is called.

satya - 2/12/2014 5:13:40 PM

onDestroy

Note: do not count on this method being called as a place for saving data! For example, if an activity is editing data in a content provider, those edits should be committed in either onPause() or onSaveInstanceState(Bundle), not here. This method is usually implemented to free resources like threads that are associated with an activity, so that a destroyed activity does not leave such things around while the rest of its application is still running. There are situations where the system will simply kill the activity's hosting process without calling this method (or any others) in it, so it should not be used to do things that are intended to remain around after the process goes away.

satya - 2/12/2014 5:15:12 PM

if the process is in place, then it will be called...

so don't ignore it for inprocess cleanups. If the process goes away then all is gone. But if you have a critical external resource that must be controlled use the isFinishing() and onPause() combination.

satya - 2/13/2014 11:11:19 AM

Here is an annotated image for the activity life cycle

satya - 2/13/2014 11:12:42 AM

Timing of onSaveInstanceState()

although it is shown to be before onStop(), the SDK does not guarantee that this is either before or after onStop!!

satya - 2/13/2014 11:47:45 AM

onCreate what you should and shouldn't do

When onCreate is called an activity may be in one of 3 states. It may have been a brand new activity starting out its life for the first time. Or it may be an activity that is restarted because of a configuration change. Or it is an activity that is restarted following a previous process shutdown due to low memory and low priority.

An onCreate should take these scenarios into account.

At a minimum it is in onCreate that you load your view hierarchies by loading the layouts into the content view of the activity.

You have an option to look into the previous state of the activity by looking into the bundle that is passed to this method. This bundle may be because of a configuration change or because of rebirth due to previous memory consolidation. This can also be done in the onRestoreInstanceState.

This method can also look into the previous persistence state of the application saved in the onPause() method.

This method can also see if there is a non-configuration instance variable that is passed from the current local memory so that it can reestablish that connectivity. This typically happens during the configuration change. Newer approach is to use retained fragments to do that.

You also may want to ensure that in the layouts you have right views and fragments to match when the state was saved. Because a subsequent onRestoreInstance (which is called after onStart) assumes that all the view and fragment hierarchies are present to restore their respective state. Mere presence of previous state will not recreate the views. So it is up to this method to load the right layouts to be shown.

satya - 2/13/2014 11:52:57 AM

onStart what you should and shouldn't do

This method assumes that the view hierarchies are loaded and available before this method starts. You normally don't need to do anything here.

you must be aware that the restore instance state method is called after this method. So you shouldn't make assumptions about the state of the views in this method.

So try not to manipulate the state of the views in this method. Do that refinement in the onResume method.

Because this is a counterpart of the onStop(), do the reverse should you have stopped something in onStop() or in onPause().

So in fact, if you see something is being done in this method. look at it with caution and make sure it is appropriate.

Also know that start and stop cycle can happen multiple times during the over all current cycle of the activity.

satya - 2/13/2014 11:55:58 AM

onRestoreInstanceState what you should and shouldn't do

Unless you want to persistently save the state of information across activity invocations you should use this method to save most of your state here as it is retained between configuration changes, home and back etc. Only time you loose this state is if you haven't user your app for a long time or you run into low memory conditions. In that case use the onPause() to save that to a file explicitly.

You shouldn't rely on the instance state if the information is too important to loose.

satya - 2/13/2014 12:01:23 PM

onResume what you should and shouldn't do

Returning from this method is the beginning of the full view. This is where you may start your counters, or animations etc.

You can also fine tune your view state if needed.

As this method doesnt have a bundle you need to rely on the information from onCreate or onRestore to fine tune state if further needed.

you can also keep track of the case if the views are really destroyed or not by following the callback methods and see if the views are still intact or they need to be refined.

Typically you will not do state management here but only those activities that need to be turned on or off based on visibility.

satya - 2/13/2014 12:07:34 PM

onPause what you should and shouldn't do

There is enough written about this method in the sdk.

it is the last method for data that you cannot afford to loose to save it in an external file.

You cannot use this method to save a bundle.

More processing here delays other activities. Be brief.

you can go to onResume right away from here. So onResume can potentially use that fact to optimize if need be.

For instance you can tell an asynctask not to send updates from here and restart them in onResume.

satya - 2/13/2014 12:09:55 PM

onStop what you should and shouldn't do

After this call the activity is no longer visible. But keep in mind this may not be called after onPause under low memory conditions. So don't put code here that impacts out of process conditionals.

satya - 2/13/2014 12:10:55 PM

onDestroy what you should and shouldn't do

Much like onstop, doon't put code that controls external processes. But you can certainly put code that stops threads with in the same process etc.

satya - 2/13/2014 12:12:13 PM

onRestart what you shoudl and shouldn't do

this method is quite useful to know if the view state is really intact by setting a flag and repump or restart something that is stopped earlier due to a stop but destroy not called.

satya - 2/13/2014 12:15:32 PM

onNonConfigurationInstance

Although deprecated this method is really useful when activities are reborn. This gives an opportunity to save reference or pointer to a memory object that is tied to this activity and wants to know the new address of the activity.

You can also use headless retained fragments for this as they have additional benefit of being able to track the activity life cycle and not just the reference to the activity.

See my notes on ADOs (Activity Dependpent Objects) to understand this method better.

satya - 2/15/2014 9:12:29 AM

Another attempt at nailing down instance state

the state the user is willing to let go when the android activity is explicitly closed by the user by either clicking the back button or other means. So this state is used and useful for the lifetime of the activity and no expectations of being used or recalled beyond that.