Skip to content
Module 5 of 20

Android activity lifecycle

Android activity lifecycle states, callbacks, configuration changes, and how to preserve UI state.

Learning Objectives

By the end of this module, you’ll understand:

  • Why Activities have a lifecycle
  • How Android creates and destroys Activities
  • Every lifecycle callback in detail
  • The Activity state machine
  • Configuration changes
  • Process death vs Activity destruction
  • Saving and restoring state
  • Lifecycle-aware components
  • Common bugs and best practices
  • Real-world lifecycle scenarios

1. Why Does Android Need a Lifecycle?

Let’s begin with a thought experiment.

Suppose Android worked like a desktop application.

main()

↓

Window Opens

↓

Runs Forever

↓

User Closes

↓

Exit

Would this work on a phone?

No.

Phones have limited:

  • RAM
  • CPU
  • Battery
  • Storage

And users constantly switch between apps.

Example:

Instagram

↓

Camera

↓

WhatsApp

↓

Chrome

↓

Maps

↓

Phone Call

↓

Back to Instagram

Should Instagram stay fully active the entire time?

No.

That would:

  • waste battery
  • consume memory
  • reduce performance
  • make multitasking impossible

Android therefore manages app lifecycles aggressively.


2. Android Owns Your Activity

One of the biggest misconceptions:

“I create my Activity.”

Actually, Android does.

When you write:

class MainActivity : AppCompatActivity()

you’re defining a blueprint.

The actual creation looks more like:

User taps icon

↓

Android System

↓

Creates MainActivity

↓

Calls lifecycle callbacks

Your Activity exists because Android instantiated it—not because you called a constructor.


3. Think of an Activity as an Actor

Imagine an actor in a theater.

They don’t decide:

  • when to enter
  • when to leave
  • when to pause

The director does.

Android is the director.

Android

↓

Create Activity

↓

Start Activity

↓

Pause Activity

↓

Resume Activity

↓

Destroy Activity

Your Activity simply responds to instructions.


4. The Complete Lifecycle

Here is the full lifecycle:

           onCreate()

                │

                ▼

           onStart()

                │

                ▼

          onResume()

                │

      Activity Running

                │

       User Leaves App

                │

                ▼

           onPause()

                │

                ▼

            onStop()

                │

       Return to App

                │

        onRestart()

                │

        onStart()

                │

       onResume()

                │

       Finish Activity

                │

       onDestroy()

This isn’t just a sequence.

It’s a state machine.

Android moves your Activity between states depending on what the user and system are doing.


5. Activity States

An Activity is always in one of several logical states.

Created

↓

Started

↓

Resumed

↓

Paused

↓

Stopped

↓

Destroyed

Only one Activity is typically in the Resumed state at a time because that’s the one interacting with the user.


6. onCreate()

This is the first callback after Android creates the Activity instance.

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    setContentView(R.layout.activity_main)
}

Think of it as:

“Build everything needed for this screen.”

Typical responsibilities:

  • Inflate the layout
  • Initialize ViewBinding
  • Create ViewModel references
  • Restore saved state
  • Configure RecyclerViews
  • Set click listeners

Avoid:

  • Long-running work
  • Blocking the main thread
  • Heavy network calls directly

onCreate() is called once per Activity instance.

If Android destroys the Activity and creates a new one (e.g., rotation), the new instance gets its own onCreate().


7. onStart()

The Activity is now becoming visible.

onCreate()

↓

onStart()

↓

User can SEE it

↓

Not yet interacting

Use this for work tied to visibility.

Examples:

  • Register listeners
  • Start observing data (when appropriate)
  • Prepare UI resources

8. onResume()

This is when the Activity moves to the foreground and the user can interact with it.

Activity

↓

Visible

↓

Interactive

↓

Receiving Touch Events

Good places to:

  • Start animations
  • Resume camera preview
  • Resume sensors
  • Resume gameplay

When onResume() finishes, the user is actively using your screen.


9. onPause()

This callback happens when the Activity is losing focus, but it may still be partially visible.

Example:

User opens dialog

↓

Current Activity

↓

onPause()

Or:

Incoming phone call

↓

onPause()

onPause() should be fast.

Typical tasks:

  • Pause animations
  • Pause camera
  • Commit lightweight changes
  • Stop exclusive resources

Avoid lengthy operations because the next Activity is waiting for yours to pause.


10. onStop()

The Activity is no longer visible.

Home Button

↓

onPause()

↓

onStop()

Now is a good time to:

  • Release larger resources
  • Stop UI updates
  • Unregister listeners tied to visibility
  • Stop observing data that isn’t needed in the background

The Activity object may still exist in memory.


11. onRestart()

If the Activity was stopped but not destroyed, returning to it triggers:

onRestart()

↓

onStart()

↓

onResume()

This gives you a chance to prepare the Activity before it becomes visible again.


12. onDestroy()

This is the final callback before the Activity instance is destroyed.

Reasons include:

  • User finishes the Activity
  • Configuration change (like rotation)
  • Android removes the Activity

Use it to clean up resources owned by the Activity.

Important: Do not rely on onDestroy() always being called. If the entire process is killed by the system, onDestroy() may never execute.


13. What Happens During Screen Rotation?

One of Android’s most misunderstood behaviors.

Suppose the user rotates the device.

Many assume:

Rotate

↓

UI rotates

That’s not what Android normally does.

Instead:

Portrait Activity

↓

onPause()

↓

onStop()

↓

onDestroy()

↓

New Activity Instance

↓

onCreate()

↓

onStart()

↓

onResume()

Why?

Because resources change:

  • Layouts
  • Dimensions
  • Drawables
  • Language
  • Orientation-specific resources

Recreating the Activity ensures everything is reloaded correctly.


14. Configuration Changes

Rotation is just one configuration change.

Others include:

  • Language change
  • Font scale
  • Screen size
  • Dark mode
  • Locale
  • UI mode
  • Display density

Most configuration changes recreate the Activity so it can load the correct resources.


15. Activity Destruction vs Process Death

These are not the same.

Activity Destruction

Activity

↓

Destroyed

↓

Process Still Alive

Example:

You press Back.

Only that Activity is removed.


Process Death

Activity

↓

Process

↓

Everything Gone

Example:

Your app is in the background.

System needs RAM.

Android kills the entire process.

Later:

User returns

↓

Entire Process Starts Again

This is why relying only on in-memory variables is dangerous.


16. Saving UI State

Imagine the user types:

Username

↓

John

Then rotates the phone.

Without saving state:

Rotation

↓

Activity recreated

↓

EditText empty ❌

Android provides onSaveInstanceState().

override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
    outState.putString("username", username)
}

Restore it in onCreate():

val username = savedInstanceState?.getString("username")

17. ViewModel and Configuration Changes

Before ViewModel:

Rotate

↓

Activity Destroyed

↓

Data Lost

↓

Reload API

With ViewModel:

Rotate

↓

Activity Destroyed

↓

ViewModel Survives

↓

Activity Recreated

↓

Reuse Existing Data

This is one of the main reasons ViewModel exists.

We’ll dive deeply into ViewModel in a later module.


18. Lifecycle-Aware Components

Jetpack introduced lifecycle-aware APIs to reduce bugs.

Instead of manually managing every callback, components can observe the lifecycle.

For example, using repeatOnLifecycle with coroutines ensures collection only happens while the UI is in an active state:

lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.STARTED) {
        viewModel.uiState.collect { state ->
            // Update UI
        }
    }
}

This prevents leaks and unnecessary work when the Activity isn’t visible.


19. Common Lifecycle Bugs

Bug 1: Duplicate API Calls

onCreate()

↓

API Request

↓

Rotate

↓

New onCreate()

↓

Another API Request

Solution:

Move data loading to the ViewModel and cache results appropriately.


Bug 2: Memory Leak

Holding a reference to the Activity after it’s destroyed:

Singleton

↓

Activity Reference

↓

Activity Destroyed

↓

Reference Still Exists ❌

The garbage collector can’t reclaim the Activity.


Bug 3: Lost State

Rotate

↓

Activity Destroyed

↓

Counter = 0

Use savedInstanceState for transient UI state and ViewModel for screen-related data.


Bug 4: Updating a Dead Activity

Network Request

↓

Activity Destroyed

↓

Response Arrives

↓

Crash

Lifecycle-aware coroutines and proper scoping (e.g., viewModelScope, lifecycleScope) help prevent this.


20. Real-World Example

Imagine a YouTube-like app.

User opens video

↓

onCreate()

↓

Load player

↓

onStart()

↓

Show controls

↓

onResume()

↓

Video plays

↓

Home button

↓

onPause()

↓

Pause playback

↓

onStop()

↓

Release rendering resources

↓

User returns

↓

onRestart()

↓

onStart()

↓

onResume()

↓

Resume playback

Notice how each callback has a specific responsibility.


Best Practices

  • Keep onCreate() focused on initialization.
  • Use onStart()/onStop() for work tied to visibility.
  • Use onResume()/onPause() for work requiring user interaction (camera, sensors, animations).
  • Never perform heavy work on the main thread.
  • Assume your Activity can be destroyed at any time.
  • Use ViewModel for screen data that should survive configuration changes.
  • Use savedInstanceState for temporary UI state (e.g., scroll position, text input).
  • Prefer lifecycle-aware APIs over manual callback management.

Mental Model

Instead of memorizing callbacks, remember this story:

Android creates your Activity
            │
            ▼
Initialize everything (onCreate)
            │
            ▼
Make it visible (onStart)
            │
            ▼
Allow user interaction (onResume)
            │
            ▼
Temporarily lose focus (onPause)
            │
            ▼
Become invisible (onStop)
            │
            ▼
Possibly return (onRestart)
            │
            ▼
Eventually be destroyed (onDestroy)

If you understand why each transition happens, you’ll rarely need to memorize the order.


Interview Questions

  1. Why does Android use an Activity lifecycle instead of a main() method?
  2. Explain the difference between onPause() and onStop().
  3. What happens internally when the device is rotated?
  4. How does ViewModel help during configuration changes?
  5. What’s the difference between Activity destruction and process death?
  6. Why shouldn’t you rely on onDestroy() for critical cleanup?
  7. When should you use savedInstanceState versus a ViewModel?
  8. What kinds of work belong in onResume() but not onCreate()?
  9. Why are lifecycle-aware APIs like repeatOnLifecycle recommended?
  10. Describe a real-world lifecycle bug you’ve encountered or how you’d prevent one.

Up Next: Module 6 – Fragments (Deep Dive)

This won’t just be “Fragments are reusable UI.” We’ll cover:

  • Why Google introduced Fragments
  • The relationship between Activities and Fragments
  • The complete Fragment lifecycle (and how it differs from Activity)
  • onCreateView() vs onViewCreated()
  • Why onDestroyView() is one of the most important callbacks
  • FragmentManager and Fragment transactions
  • Navigation Component and modern Fragment usage
  • Common Fragment memory leaks and lifecycle pitfalls
  • Why many modern Compose apps use a single-Activity architecture, and where Fragments still fit today

By the end, you’ll understand not only how to use Fragments, but also when they are the right architectural choice.