← Back to list

What is the Android Activity Lifecycle and Explain Flow with UI Diagram also?

Android Activity Lifecycle: A Complete Guide with Flow Diagram

SURYA PRAKASH · 2026-07-01 17:57 · 0 claps · 5.9 min read
#android-activity #activity-lifecycle #android #kotlin #android-components
Open on Medium ↗
Wiki topics: 📱 · Mobile Development

What is the Android Activity Lifecycle and Explain Flow with UI Diagram also?

Android Activity Lifecycle: A Complete Guide with Flow Diagram

Everything you need to know about how Android manages your Activity’s life — from first launch to final destruction.

Why the Lifecycle Matters:

Every Android developer eventually hits that dreaded bug: the app crashes on rotation, data disappears when the user gets a phone call, or animations restart from scratch after pressing Home. Almost every one of these bugs traces back to one root cause — not understanding the Activity lifecycle.

The Android system controls when your app runs, not you. It can pause, stop, or outright kill your activity based on memory pressure, user actions, or system events. The lifecycle callbacks are Android’s way of giving you a chance to save state, release resources, and restore things gracefully.

Mastering this is not optional — it’s the foundation of every stable Android app.

The Lifecycle at a Glance:

An Activity passes through a series of states. Android fires a callback method each time it transitions between them. Here are all six (plus onRestart):

CallbackState enteredWhat it signalsonCreate()CreatedActivity created for the first timeonStart()StartedActivity becoming visibleonResume()ResumedActivity in the foreground, user can interactonPause()PausedPartially obscured or interruptedonStop()StoppedFully hidden from the useronDestroy()DestroyedActivity torn down completelyonRestart()—Returning from stopped (not destroyed) state

The flow diagram above shows how these states connect, including the re-entry path via onRestart().

Each Callback, Explained Here:

1). onCreate() — the beginning:

This is called once when the activity is first created. It’s where you set everything up.

class MainActivity : AppCompatActivity() {

private lateinit var viewModel: MainViewModel
    private lateinit var binding: ActivityMainBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // Inflate layout
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        // Initialise ViewModel
        viewModel = ViewModelProvider(this)[MainViewModel::class.java]
        // Restore saved state if returning from kill
        savedInstanceState?.let {
            val savedText = it.getString("KEY_USER_INPUT", "")
            binding.editText.setText(savedText)
        }
        // Set up click listeners
        binding.button.setOnClickListener {
            viewModel.loadData()
        }
    }
}

savedInstanceState is non-null only if the activity was previously destroyed by the system and is being recreated — such as after a screen rotation or memory reclaim.

2). onStart() — becoming visible:

Called every time the activity becomes visible to the user, both on first launch and when returning from the back stack or another activity.

override fun onStart() {
    super.onStart()
// Re-register a broadcast receiver
    registerReceiver(networkReceiver, IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION))
    // Refresh UI data that may have changed while away
    viewModel.refreshUserProfile()
}

The activity is now visible but may not yet be interactive. Avoid starting animations or input capture here.

3). onResume() — the active foreground state:

This is called when the activity moves to the foreground and the user can fully interact with it. It’s also called every single time the activity comes back from onPause(), such as after dismissing a dialog.

override fun onResume() {
    super.onResume()
// Resume camera preview
    cameraPreview.start()
    // Resume location updates
    locationManager.requestLocationUpdates(provider, 1000L, 1f, locationListener)
    // Resume animations
    animationView.resumeAnimation()
}

This is the “running” state. Your app is alive, visible, and interactive.

4). onPause() — first sign of interruption:

Called when another activity comes to the foreground — such as a dialog, an incoming call overlay, or a split-screen companion. The current activity is still partially visible but is no longer the focus.

override fun onPause() {
    super.onPause()
// Pause camera - another activity may need it
    cameraPreview.stop()
    // Pause location updates - save battery
    locationManager.removeUpdates(locationListener)
    // Pause animations
    animationView.pauseAnimation()
    // Lightweight state save - onPause must be FAST
    viewModel.saveCurrentScrollPosition(binding.recyclerView.computeVerticalScrollOffset())
}

Keep onPause() fast. The system will not transition the new activity to onResume() until your onPause() returns. Heavy operations here delay the incoming screen.

5). onStop() — fully hidden:

Called when the activity is completely invisible to the user — either because the user navigated away, another full-screen activity launched, or the user pressed Home.

override fun onStop() {
    super.onStop()
// Unregister receivers no longer needed
    unregisterReceiver(networkReceiver)
    // Persist data to Room/disk
    viewModel.saveNoteToDatabase(binding.noteEditText.text.toString())
    // Release heavy resources (video players, sensors)
    videoPlayer.release()
}

This is a safe place to do heavier saves than onPause() allows, since onStop() runs on the main thread but doesn't have the same time pressure.

6). onRestart() — returning from stopped:

If the user navigates back to your activity after it was stopped (but not destroyed), onRestart() is called before onStart(). You rarely need to override this, but it's useful for re-checking state that may have changed while the user was away.

override fun onRestart() {
    super.onRestart()
    // The activity is coming back from a stopped state
    // onStart() will follow immediately after this
    viewModel.checkIfDataChangedWhileStopped()
}

7). onDestroy() — the end:

Called before the activity is destroyed. This can happen because:

  1. The user or app called finish()
  2. The system destroyed the activity to reclaim memory
  3. A configuration change (like rotation) is occurring
override fun onDestroy() {
    super.onDestroy()
// Check if it's a real destroy vs a config change
    if (isFinishing) {
        // True destroy - clean up permanent resources
        database.close()
        analyticsTracker.flush()
    }
    // Note: ViewModel survives config changes, so don't destroy it here
    // ViewModels clean themselves up via onCleared()
}

Saving and Restoring State:

When Android kills your process to reclaim memory, it can restore the activity later — but only if you saved the state first. Use onSaveInstanceState() for UI state and ViewModel for data.

kotlin

// Save lightweight UI state before the system may kill the process
override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
    outState.putString("KEY_USER_INPUT", binding.editText.text.toString())
    outState.putInt("KEY_SCROLL_POS", binding.recyclerView.computeVerticalScrollOffset())
}

// Restore in onCreate() or onRestoreInstanceState()
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
    super.onRestoreInstanceState(savedInstanceState)
    binding.editText.setText(savedInstanceState.getString("KEY_USER_INPUT"))
}

For anything heavier — network data, parsed models, business logic state — use a ViewModel. It survives configuration changes automatically.

Lifecycle in Practice: Common Scenarios:

Scenario 1 — User rotates the screen

onPause() → onStop() → onDestroy()
onCreate() → onStart() → onResume()

The activity is recreated from scratch. ViewModel data survives; UI state must be saved via onSaveInstanceState().

Scenario 2 — User presses Home

onPause() → onStop()
(App process may be killed here by the system)

When the user returns: onRestart() → onStart() → onResume() (if not killed), or the full onCreate() path if the process was killed.

Scenario 3 — Incoming phone call

onPause()     ← dialer comes to foreground
onStop()      ← dialer is full-screen
(call ends)
onRestart() → onStart() → onResume()

Scenario 4 — Starting a new Activity

ActivityA: onPause()
ActivityB: onCreate() → onStart() → onResume()
ActivityA: onStop()    ← only after B is visible

Note that A’s onStop() happens after B's onResume(). This is why onPause() must be fast.

Lifecycle with Jetpack:

Lifecycle-aware components

Jetpack’s Lifecycle API lets you move lifecycle logic out of the activity and into reusable components:

class LocationTracker(private val context: Context) : DefaultLifecycleObserver {

override fun onStart(owner: LifecycleOwner) {
        startTracking()
    }
    override fun onStop(owner: LifecycleOwner) {
        stopTracking()
    }
    private fun startTracking() { /* ... */ }
    private fun stopTracking() { /* ... */ }
}
// In your Activity
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        lifecycle.addObserver(LocationTracker(this))
    }
}

The LocationTracker now self-manages — you never have to call startTracking() or stopTracking() manually.

repeatOnLifecycle for Flow collection:

kotlin

lifecycleScope.launch {
    // Only collects when the lifecycle is STARTED or above
    // Automatically cancels on STOP, re-collects on START
    repeatOnLifecycle(Lifecycle.State.STARTED) {
        viewModel.uiState.collect { state ->
            updateUi(state)
        }
    }
}

This is the modern, safe way to collect Flow in an Activity. It's lifecycle-aware and won't waste work when the activity is in the background.

Common Mistakes to Avoid:

Starting heavy operations in onResume() without cleanup in onPause() is a resource leak — anything you start in onResume() must be stopped in onPause(). Similarly, registering a receiver in onStart() and forgetting to unregister it in onStop() causes crashes after the activity is destroyed. Storing an Activity reference anywhere that outlives the lifecycle — a singleton, a static field, a ViewModel property typed as Activity — causes memory leaks. And performing heavy I/O inside onPause() will delay the incoming activity from becoming interactive, since the system waits for onPause() to finish.

Summary:

The Android Activity lifecycle is a contract between your app and the system. Understanding it means you can:

  • Save and restore state correctly across rotations and process kills
  • Release resources (camera, GPS, sensors) exactly when they’re no longer needed
  • Build smooth UX transitions without stutter or crashes
  • Write lifecycle-aware components that clean up after themselves

The flow diagram above is a map — refer to it whenever you’re unsure which callback fires in which situation.

Found this helpful? Follow for more Android deep-dives. Up next: Fragment Lifecycle & the Back Stack explained.

Tags: #AndroidDevelopment #Kotlin #Android #MobileDev #ActivityLifecycle


메타데이터
post_id
2a7de2a56751
slug
what-is-the-android-activity-lifecycle-and-explain-flow-with-ui-diagram-also-2a7de2a56751
url
https://medium.com/@suryaprakash2088/what-is-the-android-activity-lifecycle-and-explain-flow-with-ui-diagram-also-2a7de2a56751
canonical_url
https://medium.com/@suryaprakash2088/what-is-the-android-activity-lifecycle-and-explain-flow-with-ui-diagram-also-2a7de2a56751
author_url
https://medium.com/@suryaprakash2088
status
ok
fetched_at
2026-08-31 15:21:15