Android Activity Lifecycle: A Developer's Guide to Mastering App States

Hey there! If you've ever built an Android app or are just getting started with Android development, understanding the Android Activity Lifecycle is crucial. Think of it as your app’s heartbeat it governs how your app behaves when users interact with it, switch between apps, rotate screens, or even receive a phone call.
The Android Activity Lifecycle consists of several key stages that every activity goes through from creation to destruction. Each stage has its own callback methods like onCreate()
, onStart()
, and onResume()
which help manage transitions between different states such as Created, Started, Resumed, Paused, Stopped, Restarted, and Destroyed.
In this article, we’ll walk through each lifecycle state, explain what happens under the hood, and share some real-world scenarios where knowing these callbacks can save your day (and your app!). Let’s dive in!
Key Lifecycle States & Callbacks
Before jumping into deeper waters, let’s first understand the six core lifecycle states every Android activity passes through:
State | Description | Callback(s) |
---|---|---|
Created | The activity is initialized | onCreate() → onStart() |
Started | Activity becomes visible but not yet interactive | onStart() |
Resumed | Activity is in the foreground and ready for user interaction | onResume() |
Paused | Partially obscured by another activity | onPause() |
Stopped | No longer visible | onStop() |
Restarted | Coming back from Stopped state | onRestart() → onStart() → onResume() |
Destroyed | Activity is being removed from memory | onDestroy() |
These callbacks act as entry points for developers to perform setup, clean up resources, or respond to state changes dynamically.
How to Use Android Activity Lifecycle Effectively
Let’s take a closer look at each callback and what you should (or shouldn’t) do inside them.
onCreate()
: Where It All Begins
This is where your activity is first created. Here’s where you typically initialize UI components, bind data, and set up ViewModels or LiveData observers.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initialize ViewModel
viewModel = new ViewModelProvider(this).get(MyViewModel.class);
}
💡 Pro tip: Always call super.onCreate(savedInstanceState)
first to ensure proper initialization by the system.
onStart()
: Going Visible
Once onCreate()
completes, the activity enters the Started state. This is where you might register BroadcastReceivers or start animations that need to run while the screen is visible [[3]][[8]].
@Override
protected void onStart() {
super.onStart();
registerReceiver(myReceiver, intentFilter);
}
onResume()
: Front and Center
Now the activity is fully interactive. This is the ideal place to start sensors, resume gameplay, or reconnect to services.
@Override
protected void onResume() {
super.onResume();
sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
}
⚠️ Remember: Anything started here should be paused or cleaned up in onPause()
to avoid unnecessary battery drain.
onPause()
: When Things Get Interrupted
This callback runs when your activity is partially obscured think incoming calls, pop-up dialogs, or switching apps. Save temporary state here using SharedPreferences or ViewModel.
@Override
protected void onPause() {
super.onPause();
sensorManager.unregisterListener(this);
saveUserProgress(); // e.g., save draft content
}
onStop()
: Out of Sight
When your activity isn’t visible anymore, onStop()
gets called. Free up resources like camera access, unregister listeners, or disconnect from APIs here.
@Override
protected void onStop() {
super.onStop();
if (locationClient != null) {
locationClient.disconnect();
}
}
onRestart()
: Back in Action
After onStop()
, if the user returns to your activity, onRestart()
gives you a chance to refresh UI elements before onStart()
and onResume()
fire again.
@Override
protected void onRestart() {
super.onRestart();
refreshDataFromServer();
}
onDestroy()
: Final Cleanup
This is the last call before your activity dies. Perform final cleanup here close database connections, cancel pending network requests, etc.
@Override
protected void onDestroy() {
super.onDestroy();
disposable.clear(); // RxJava cleanup
}
Best Practices for Managing the Android Activity Lifecycle
Here are some tried-and-true strategies I’ve picked up over the years working with Android:
Pair Your Callbacks
Always pair your lifecycle methods to ensure resources are opened and closed correctly:
onCreate()
↔onDestroy()
onStart()
↔onStop()
onResume()
↔onPause()
This symmetry ensures your app doesn't leak memory or waste resources.
Keep UI Logic Separate
Use ViewModels, LiveData, or LifecycleObservers to decouple UI logic from your activity. This makes your code more testable and lifecycle-aware.
viewModel.getUser().observe(this, user -> {
updateUI(user);
});
Save State Early
Use onPause()
to persist important user data. Don’t wait until onStop()
or onDestroy()
those may never get called if the system kills your process abruptly.
Avoid Long-Running Tasks in Callbacks
Never block lifecycle methods with long-running operations like file I/O or network calls. Offload them to background workers like WorkManager
or Service
instead.
Real-World Scenarios & Flow Breakdown
Let’s explore some common situations and how the lifecycle responds:
Navigating Away (e.g., Phone Call)
- User receives a call
- App flow:
onPause()
→ (maybeonStop()
) → back →onResume()
Pressing Home / Switching Apps
- App moves to background
- Flow:
onPause()
→onStop()
→ reopen →onRestart()
→onStart()
→onResume()
Screen Rotation / Multi-Window Mode
By default, Android destroys and recreates the activity unless you handle configuration changes manually.
- Flow:
onPause()
→onStop()
→onDestroy()
→onCreate()
→onStart()
→onResume()
💡 Tip: Use ViewModel
or onSaveInstanceState()
to retain transient UI state across recreation.
Common Mistakes to Avoid
- ❌ Performing heavy operations in
onCreate()
oronResume()
- ❌ Forgetting to unregister receivers/listeners in
onPause()
oronStop()
- ❌ Not saving user progress early enough (e.g., relying only on
onDestroy()
) - ❌ Assuming
onDestroy()
will always be called
Tips for Mastering the Android Activity Lifecycle
- Use Logging: Add log statements to each lifecycle method during development to visualize the flow.
- Test Edge Cases: Rotate the device, simulate low-memory conditions, and test background behavior.
- Leverage Lifecycle-Aware Components: Use
ViewModel
,LiveData
, andLifecycleObserver
to simplify state management. - Profile with Tools: Use Android Studio Profiler to detect leaks or unexpected pauses.
Conclusion: You're Now a Lifecycle Pro!
Understanding the Android Activity Lifecycle is more than just memorizing callbacks it’s about writing robust, responsive, and resource-efficient apps. Whether you're debugging strange UI behavior, handling interruptions gracefully, or optimizing performance, mastering the lifecycle puts you in control.
So next time you’re building that killer feature, remember: always ask yourself Which lifecycle method is the right one for this task? And now, you’ve got the tools to answer that confidently.
Got questions or want to dive deeper into ViewModel or LiveData integration? Leave a comment below or check out our other guides on modern Android architecture components. Happy coding!