Every Android screen you build is an Activity, and every Activity goes through the same predictable sequence of states from the moment it appears to the moment it is destroyed. Android tells you about each transition by calling a callback method.
Get these right and your app remembers what the user was doing. Get them wrong and it loses their work when the phone rings.
An Activity is one screen the user can look at and interact with. A quiz app might have a question screen and a results screen โ that is two Activities.
Android calls these on your Activity as its state changes. You override the ones you care about.
| Callback | Fires when | Typical use |
|---|---|---|
onCreate() | The Activity is first created | Set up views, restore state. Required. |
onStart() | It becomes visible | Start things the user should see |
onResume() | It becomes interactive | Start animations, camera, sensors |
onPause() | It loses focus | Save data. Stop animations |
onStop() | It is no longer visible | Release heavier resources |
onRestart() | A stopped Activity is coming back | Re-acquire what onStop released |
onDestroy() | It is being torn down | Final cleanup |
onCreate), open the doors (onStart), serve customers (onResume), close for lunch (onPause), shut the doors for the evening (onStop), and eventually close the business for good (onDestroy).The fastest way to understand the lifecycle is to watch it happen. Override every callback and log it:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "Cycle";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, "onCreate:");
}
@Override protected void onStart() { super.onStart(); Log.d(TAG, "onStart:"); }
@Override protected void onResume() { super.onResume(); Log.d(TAG, "onResume:"); }
@Override protected void onPause() { super.onPause(); Log.d(TAG, "onPause:"); }
@Override protected void onStop() { super.onStop(); Log.d(TAG, "onStop:"); }
@Override protected void onRestart() { super.onRestart(); Log.d(TAG, "onRestart:"); }
@Override protected void onDestroy() { super.onDestroy(); Log.d(TAG, "onDestroy:"); }
}Always call the super version first. Android does its own bookkeeping in there, and skipping it causes real bugs.
Now run the app, open Logcat, and filter for Cycle. Try each of these:
Launching the app gives you the startup sequence:
onCreate:
onStart:
onResume:Pressing Home โ the Activity leaves the screen but stays in memory:
onPause:
onStop:Returning to the app โ note that onCreate does not run again:
onRestart:
onStart:
onResume:Rotating the phone โ this one surprises everyone:
onPause:
onStop:
onDestroy:
onCreate:
onStart:
onResume:The Activity is completely destroyed and recreated. Any value held in a plain field is gone. This is the single most common source of "why did my app forget everything?" bugs.
Three rules cover almost every case.
Set up in onCreate(). This runs once per Activity instance. Inflate the layout, find your views, attach listeners.
Save in onPause(). This is the last callback you are guaranteed to get. Android can kill a stopped Activity without ever calling onStop() or onDestroy(), so anything the user would hate to lose is saved here.
Release in onStop(). If the screen is not visible, stop doing expensive work โ GPS, sensors, network polling. It drains the battery and the user cannot see the result anyway.
A common mistake is putting "save the user's work" inonDestroy(). On a low-memory device that method may never be called. UseonPause().
Since rotation destroys and recreates the Activity, you need to hand the important values across the gap. Android gives you a Bundle for exactly this:
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("SCORE", score);
outState.putInt("INDEX", currentIndex);
}Then read it back in onCreate():
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState != null) {
score = savedInstanceState.getInt("SCORE");
currentIndex = savedInstanceState.getInt("INDEX");
}
}That savedInstanceState != null check matters. On a genuinely fresh launch the Bundle is null; it only holds data when Android is restoring an Activity it destroyed.
onSaveInstanceState is packing a small bag before a trip. You cannot take the whole room with you โ just the few things you will need to set it up again on the other side.onCreate โ onStart โ onResumeonPause โ onStop; coming back gives onRestart โ onStart โ onResumeonCreate, save in onPause, release in onStoponSaveInstanceState() to carry values across a recreationsuper firstThe best way to internalise this is still the logging exercise above. Run it, rotate the phone, press Home, and watch the order the callbacks fire in.