Question #440MediumNative AndroidImportant

What is the lifecycle of an Android application?

#android#lifecycle#activity#oncreate#onresume#onpause#ondestroy#flutter

Answer

Overview

Android application lifecycle defines how the Android OS creates, pauses, resumes, and destroys app components. Understanding it is critical for managing resources, saving state, and building stable apps.

Android lifecycle operates at two main levels:

  • Application level — the entire app process
  • Activity level — each individual screen

Application Lifecycle

The

text
Application
class is instantiated before any Activity. It represents the entire app process.

kotlin
class MyApplication : Application() {

    override fun onCreate() {
        super.onCreate()
        // Called when the app process is first created
        // ✅ Use for: app-wide init (Firebase, Timber, DI, crash reporting)
        FirebaseApp.initializeApp(this)
        Timber.plant(Timber.DebugTree())
    }

    override fun onLowMemory() {
        super.onLowMemory()
        // Called when the overall system is running low on memory
        // ✅ Use for: releasing caches, large bitmaps
    }

    override fun onTrimMemory(level: Int) {
        super.onTrimMemory(level)
        // Called when the OS wants the app to trim its memory usage
        when (level) {
            TRIM_MEMORY_UI_HIDDEN -> clearUiCaches()
            TRIM_MEMORY_RUNNING_CRITICAL -> releaseAllCaches()
        }
    }

    override fun onTerminate() {
        super.onTerminate()
        // ⚠️ Only called in emulators — NEVER called on real devices
        // Do NOT rely on this for cleanup
    }
}

Register it in

text
AndroidManifest.xml
:

xml
<application
    android:name=".MyApplication"
    ... >

Activity Lifecycle

The Activity lifecycle is the core of Android development. Each screen (Activity) moves through these states as the user navigates.

text
          ┌─────────────────────────────────┐
          │          App Launched           │
          └──────────────┬──────────────────┘
                    ┌─────────┐
                    │onCreate()│  ← Activity created, inflate UI
                    └────┬─────┘
                    ┌─────────┐
                    │onStart() │  ← Activity visible but not interactive
                    └────┬─────┘
                    ┌──────────┐
                    │onResume()│  ← Activity in foreground, user can interact
                    └────┬─────┘
          ┌──────────────┴──────────────────┐
          │        RUNNING (Active)         │
          └──────────────┬──────────────────┘
               ┌─────────┴─────────┐
               │                   │
               ▼                   ▼
         ┌──────────┐        ┌──────────┐
         │onPause() │        │onPause() │
         └────┬─────┘        └────┬─────┘
              │                   │
     Another activity       Back button /
     partially covers        fully hidden
              │                   │
              ▼                   ▼
         (still visible)    ┌──────────┐
                            │onStop()  │ ← Activity fully hidden
                            └────┬─────┘
                      ┌──────────┴──────────┐
                      │                     │
                      ▼                     ▼
               ┌────────────┐        ┌─────────────┐
               │onRestart() │        │onDestroy()  │ ← Permanently destroyed
               └─────┬──────┘        └─────────────┘
               ┌──────────┐
               │onStart() │  (back in lifecycle)
               └──────────┘

Activity Lifecycle Methods — Detailed

1. onCreate()

Called once when the Activity is first created. Set up UI, initialize ViewModel, restore saved state.

kotlin
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)

        // Initialize ViewModel
        viewModel = ViewModelProvider(this)[MainViewModel::class.java]

        // Restore state if activity was recreated (rotation, etc.)
        savedInstanceState?.let {
            val savedText = it.getString("input_text", "")
            binding.editText.setText(savedText)
        }

        // Set up UI listeners
        binding.button.setOnClickListener { viewModel.loadData() }

        // Observe LiveData
        viewModel.data.observe(this) { data ->
            binding.textView.text = data
        }
    }
}

✅ Do: Initialize views, ViewModel, observers, restore instance state ❌ Don't: Start animations, acquire camera/GPS, heavy background work


2. onStart()

Called when the Activity becomes visible to the user (but not yet interactive).

kotlin
override fun onStart() {
    super.onStart()
    // Activity is visible — but not yet in foreground
    // ✅ Use for: registering broadcast receivers, starting animations
    // ✅ Use for: resuming operations paused in onStop()
    registerReceiver(networkReceiver, IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION))
}

✅ Do: Register broadcast receivers, resume animations ❌ Don't: Acquire exclusive resources (camera, microphone)


3. onResume()

Called when the Activity is in the foreground and fully interactive. This is the "running" state.

kotlin
override fun onResume() {
    super.onResume()
    // Activity is fully interactive
    // ✅ Use for: start camera preview, resume video/audio, refresh data
    cameraPreview.start()
    sensorManager.registerListener(sensorListener, sensor, SensorManager.SENSOR_DELAY_UI)
    viewModel.refreshIfNeeded()
}

✅ Do: Start camera, sensors, video/audio playback, refresh UI data ❌ Don't: Do heavy initialization (too late, causes jank)


4. onPause()

Called when the Activity is partially obscured — another Activity is in front (e.g., dialog, transparent activity). The Activity is still visible but not focused.

kotlin
override fun onPause() {
    super.onPause()
    // Activity partially hidden — release resources that waste battery/CPU
    // ✅ Use for: pause camera, sensors, video, save draft data
    // ⚠️ Keep this method FAST — the new activity won't resume until this returns
    cameraPreview.stop()
    sensorManager.unregisterListener(sensorListener)
    viewModel.saveDraft(binding.editText.text.toString())
}

✅ Do: Pause camera, sensors, playback, save lightweight state ❌ Don't: Do heavy work, async operations, save large data (blocks UI)


5. onStop()

Called when the Activity is completely hidden — another Activity covers it entirely, or user presses Home.

kotlin
override fun onStop() {
    super.onStop()
    // Activity fully hidden — save data, release resources
    // ✅ Use for: unregister broadcast receivers, save to database
    // ✅ Safe to do heavier saves here (unlike onPause)
    unregisterReceiver(networkReceiver)
    viewModel.saveToDatabase() // Safe — runs on worker thread
}

✅ Do: Save persistent data, unregister receivers, release heavy resources ❌ Don't: Rely on this always being called before

text
onDestroy()
(system may skip it)


6. onRestart()

Called when the Activity is coming back from stopped state (user pressed Back from another activity, or returns from background).

kotlin
override fun onRestart() {
    super.onRestart()
    // Activity is being restarted after being stopped
    // Called only when coming back — NOT on fresh launch
    // ✅ Use for: refresh stale data, re-check permissions
    viewModel.refreshData()
}

Lifecycle after

text
onRestart()
: →
text
onStart()
text
onResume()


7. onDestroy()

Called when the Activity is permanently destroyed — user pressed Back,

text
finish()
was called, or system is reclaiming memory.

kotlin
override fun onDestroy() {
    // Clean up ALL remaining resources
    // ✅ Use for: cancel coroutines, close DB connections, release NDK resources
    // ✅ Check isFinishing() to distinguish user-dismissed vs system-killed
    if (isFinishing) {
        // User explicitly closed the activity
        analyticsManager.logEvent("activity_closed")
    } else {
        // System killed for recreation (e.g., rotation)
        // State already saved in onSaveInstanceState
    }
    mediaPlayer?.release()
    super.onDestroy()
}

✅ Do: Release all remaining resources, cancel background work ❌ Don't: Save important data here — it may not always be called


Saving & Restoring Instance State

When the system destroys and recreates an Activity (rotation, language change), you must save and restore UI state.

kotlin
// Save state before Activity is destroyed
override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
    outState.putString("input_text", binding.editText.text.toString())
    outState.putInt("scroll_position", binding.recyclerView.computeVerticalScrollOffset())
    outState.putBoolean("is_expanded", isExpanded)
}

// Restore state in onCreate
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(binding.root)

    savedInstanceState?.let {
        binding.editText.setText(it.getString("input_text"))
        binding.recyclerView.scrollBy(0, it.getInt("scroll_position"))
        isExpanded = it.getBoolean("is_expanded")
    }
}

Tip: Use

text
ViewModel
to survive configuration changes without
text
onSaveInstanceState
— ViewModel persists across rotation.


Lifecycle by Scenario

ScenarioMethods Called (in order)
App first launch
text
onCreate
text
onStart
text
onResume
Home button pressed
text
onPause
text
onStop
Return from background
text
onRestart
text
onStart
text
onResume
Back button pressed
text
onPause
text
onStop
text
onDestroy
Screen rotation
text
onPause
text
onStop
text
onDestroy
text
onCreate
text
onStart
text
onResume
Another activity opens (full)
text
onPause
text
onStop
Dialog / partial overlay opens
text
onPause
Phone call received
text
onPause
text
onStop
System kills app (low memory)
text
onPause
text
onStop
(process killed)
App comes to foreground after kill
text
onCreate
text
onStart
text
onResume

Process States (Android OS Perspective)

Android manages app processes in priority order. Lower priority processes are killed first when memory is needed.

StateDescriptionKilled?
ForegroundActivity in
text
onResume
— user interacting
Almost never
VisibleActivity visible but not focused (
text
onPause
)
Rarely
ServiceBackground service runningUnder pressure
BackgroundActivity in
text
onStop
, no service
Likely
Empty (Cached)No active components — process kept for fast relaunchFirst to be killed

Complete Activity Example

kotlin
class ProfileActivity : AppCompatActivity() {

    private lateinit var binding: ActivityProfileBinding
    private lateinit var viewModel: ProfileViewModel
    private var sensorManager: SensorManager? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityProfileBinding.inflate(layoutInflater)
        setContentView(binding.root)

        viewModel = ViewModelProvider(this)[ProfileViewModel::class.java]
        val userId = intent.getStringExtra("userId") ?: return finish()

        viewModel.loadProfile(userId)
        viewModel.profile.observe(this) { binding.nameText.text = it.name }

        savedInstanceState?.let {
            binding.editBio.setText(it.getString("draft_bio"))
        }
    }

    override fun onStart() {
        super.onStart()
        registerReceiver(networkReceiver, IntentFilter("android.net.conn.CONNECTIVITY_CHANGE"))
    }

    override fun onResume() {
        super.onResume()
        sensorManager?.registerListener(stepListener, stepSensor, SensorManager.SENSOR_DELAY_UI)
    }

    override fun onPause() {
        super.onPause()
        sensorManager?.unregisterListener(stepListener)
        viewModel.saveDraft(binding.editBio.text.toString())
    }

    override fun onStop() {
        super.onStop()
        unregisterReceiver(networkReceiver)
        viewModel.persistProfile()
    }

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        outState.putString("draft_bio", binding.editBio.text.toString())
    }

    override fun onDestroy() {
        sensorManager = null
        super.onDestroy()
    }
}

Flutter Integration — AppLifecycleState

In Flutter, the Activity lifecycle is exposed through

text
AppLifecycleState
via
text
WidgetsBindingObserver
.

dart
class MyScreen extends StatefulWidget {
  
  State<MyScreen> createState() => _MyScreenState();
}

class _MyScreenState extends State<MyScreen> with WidgetsBindingObserver {

  
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }

  
  void didChangeAppLifecycleState(AppLifecycleState state) {
    switch (state) {
      case AppLifecycleState.resumed:
        // Equivalent to onResume — app in foreground
        _reloadData();
      case AppLifecycleState.inactive:
        // Equivalent to onPause — partially obscured (iOS call, dialog)
        _pauseVideo();
      case AppLifecycleState.paused:
        // Equivalent to onStop — app in background
        _saveState();
      case AppLifecycleState.detached:
        // Equivalent to onDestroy — Flutter engine detached
        _cleanup();
      case AppLifecycleState.hidden:
        // Added in Flutter 3.13 — between inactive and paused
        break;
    }
  }

  
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }
}

Mapping: Android → Flutter

Android ActivityFlutter AppLifecycleState
text
onResume()
text
resumed
text
onPause()
text
inactive
text
onStop()
text
paused
text
onDestroy()
text
detached

Common Mistakes

MistakeProblemFix
Saving data only in
text
onDestroy()
May not be called if process is killedSave in
text
onStop()
or
text
onPause()
Heavy work in
text
onPause()
Blocks the incoming Activity from resumingMove to
text
onStop()
or background thread
Not unregistering receiversMemory leak, duplicate callbacksUnregister in
text
onStop()
matching
text
onStart()
Not releasing camera in
text
onPause()
Camera locked — other apps can't use itAlways release in
text
onPause()
Forgetting rotation destroys ActivityState lost on screen rotationUse
text
ViewModel
+
text
onSaveInstanceState
Calling
text
finish()
in
text
onCreate()
Activity flashes briefly before closingCall
text
return
immediately after
text
finish()