Phase 1 · Getting Started with ComposeModule 5~30 min read

Android Callback Methods

Explore animated Activity lifecycle scenarios and see how Android callbacks differ from the event callbacks your UI receives.

Understand callbacks

A callback is code supplied now so that another part of the system can call it when something happens. Android uses callbacks to tell your app that a screen is being created, shown, paused, or stopped. UI components also use callbacks to report actions such as a button tap.

  • Predict the Activity callback sequence for launch, leaving, returning, and recreation.
  • Distinguish framework lifecycle methods from a Compose onClick lambda.
  • Use Logcat to observe callbacks and avoid tying saved data to an unreliable final callback.

Who makes the call?

You override onCreate, but Android decides when to invoke it. You pass a lambda to onClick, and the button invokes it for a click. Calling a lifecycle method yourself does not reproduce a system lifecycle transition.

Explore lifecycle scenarios

Choose a scenario and play its trace. Watch the phone, Activity identity, and active callback together. Predict the next method before advancing. These scenarios show common paths with explicit assumptions; actual events and configuration can change the sequence.

Choose a scenario
Interactive walkthrough 01 / 03

Activity lifecycle explorer

Open the app with no existing Activity instance.

9:41
Initializing Activity ANot visible yet
Instance AOriginal instance
Android systemonCreate()Tap the launcher icon
CreatedCurrentStartedResumedPausedStoppedDestroyed
Callback traceInstance · method
  1. 01AonCreate()Now

onCreate()

Android creates Activity A. Initialize this instance and call setContent to host the Compose UI.

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent { AppScreen() }
}
Press Play to follow the sequence, or select any step to explore at your own pace.

An illustrated sequence, with time slowed down for learning. Real transitions can vary with task state, configuration handling, and process survival. onDestroy is not guaranteed when Android kills a process.

The seven callback methods

The core lifecycle has six callbacks, with onRestart handling a stopped Activity's return. This compact reference follows the official Activity lifecycle guide.

CallbackMeaningTypical path
onCreateInitialize this Activity instance; host the UI.New instance → onCreate → onStart
onStartThe Activity becomes visible.onStart → onResume in a normal launch
onResumeThe Activity is ready for foreground interaction.Resumed → onPause when leaving
onPauseThe Activity leaves the resumed state; it may remain visible.May resume again or proceed to onStop
onStopThe Activity is no longer visible.May restart later if its instance survives
onRestartA stopped instance is preparing to start again.onRestart → onStart
onDestroyThis instance is being destroyed normally or during recreation.Not guaranteed when the process is killed

Visibility and interaction are different. A paused Activity can still be visible in a partially covered window. Keep pause work brief, and choose resource ownership based on the actual feature.

Observe callbacks in Kotlin

Replace the Activity body in a small Compose project with this logging example. Keep the generated package and build setup. Filter Logcat by LifecycleDemo. The identity number helps you distinguish one Activity instance from the next during a single experiment.

MainActivity.kt
// Keep your project's package declaration.
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text

class MainActivity : ComponentActivity() {
    private val instance = System.identityHashCode(this)

    private fun trace(callback: String) {
        Log.d("LifecycleDemo", "Activity#$instance: $callback")
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        trace("onCreate")
        setContent {
            MaterialTheme { Text("Watch LifecycleDemo in Logcat") }
        }
    }

    override fun onStart() {
        super.onStart()
        trace("onStart")
    }

    override fun onResume() {
        super.onResume()
        trace("onResume")
    }

    override fun onPause() {
        super.onPause()
        trace("onPause")
    }

    override fun onStop() {
        super.onStop()
        trace("onStop")
    }

    override fun onRestart() {
        super.onRestart()
        trace("onRestart")
    }

    override fun onDestroy() {
        trace("onDestroy; changingConfig=$isChangingConfigurations")
        super.onDestroy()
    }
}
A diagnostic example. Each override preserves the superclass call; the logging statements observe lifecycle events.

A normal fresh launch prints onCreate → onStart → onResume. Pressing Home commonly adds onPause → onStop. Returning to the same surviving instance commonly adds onRestart → onStart → onResume. Do not assume every return reuses the instance.

User event callbacks

A click is a different event from an Activity changing state. Here, the button receives a function; it runs that function on a click. The callback updates observable state, so Compose can update the label. It does not require onCreate to run again.

Interactive walkthrough 01 / 04

A click is a callback, too

Follow a user event from a registered lambda to an updated Compose screen.

01ButtonRegister a handler
02onClickDispatch the tap
03Statecount: 0 → 1
04ComposeUpdate state readers
Illustrated buttonCount: 0Activity A · Resumed throughout

Register

Compose receives an onClick lambda while it builds the Button. The lambda is stored for a future click; its body does not run yet.

Button(onClick = { count++ }) {
    Text("Count: $count")
}
Press Play to follow the sequence, or select any step to explore at your own pace.
TapCounter.kt
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.runtime.saveable.rememberSaveable

@Composable
fun TapCounter() {
    var taps by rememberSaveable { mutableStateOf(0) }

    Button(onClick = { taps += 1 }) {
        Text("Taps: $taps")
    }
}
Call TapCounter() inside your existing setContent/theme. rememberSaveable stores this small counter through supported state restoration.

Pass an action, then let the event invoke it

In onClick = { taps += 1 }, the braces create the callback. Keep side effects out of a composable's ordinary body: composition can run again for reasons unrelated to a click.

Activity & Compose lifetimes

Recomposition reruns affected composable code. It does not recreate the Activity. A typical rotation, by contrast, destroys the old Activity and creates a new one unless the app handles that configuration change itself.

A process can disappear without a final onDestroy call. Save durable user changes when they occur and use appropriate saved state for reconstruction inputs. A ViewModel can survive configuration changes in memory; it cannot retain that memory through process death.

For production Compose screens, prefer lifecycle-aware APIsover putting all screen work in Activity overrides. For example, collectAsStateWithLifecyclecollects UI flows while its lifecycle is sufficiently active. That does not automatically stop every upstream operation. LaunchedEffect belongs to composition and its keys, so it is not a replacement name for onResume.

Predict, run & compare

  1. Cold launch the logging app. Check the initial three calls and record the Activity identity.
  2. Press Home, then return through Recents. Compare the sequence and identity with the animation.
  3. Rotate the emulator with ordinary configuration handling. Look for old-instance destruction followed by a new instance's creation.
  4. Show TapCounter(), tap three times, and verify the label changes without another Activity creation.
  5. Write one sentence for each observation: what event happened, who invoked the callback, and which lifetime changed.

Check the assumptions

If your sequence differs, first check configuration handling, device state, and whether the process survived. The animation's finish scenario represents an explicit Activity finish; a launcher-root Back gesture can have different platform behavior.

Quick check & references

Key takeaways

  • Lifecycle callbacks report changes managed by Android; event callbacks report actions such as clicks.
  • onPause does not necessarily mean invisible, and onStop does not necessarily mean destroyed.
  • Recomposition, Activity recreation, and process death are separate events with different state implications.
  • Observe with Logcat, preserve superclass behavior, and never depend on onDestroy to save the user's work.

Quick check

1. A stopped Activity returns using the same surviving instance. Which sequence is typical?

2. A button changes Compose state. Does this require another onCreate call?

3. Why should important user data not wait until onDestroy to be saved?

Read more in The Activity lifecycle, State and Jetpack Compose, and Save UI states.