Zygote
Builder trackbeginner

B01 — Hello lifecycle

Build an activity that logs every lifecycle callback, rotate the device, and watch what the system actually does. The smallest project that makes a platform mechanism visible.

3 minAPI 21–37 · 17verified 2026-10-27

An activity's lifecycle is the contract between your code and the system. It is also the first place a platform mechanism becomes observable: you can log every callback and watch the system call them in response to a rotation, a home press or a notification.

What you are building#

One activity with a logger that writes every lifecycle callback to logcat, plus a counter that survives a rotation. The screen has a button that increments the counter and a text view that shows it, so you can see the difference between state that is lost and state that is saved.

Steps#

  1. Create the project

    Create a new Compose project in Android Studio with an empty activity. Note the package name; you will filter logcat by it.

    You should seeA new project that builds and runs on the emulator.
  2. Add a tag and a logger

    Define a constant tag, for example LifecycleDemo, and a small function that logs a message with that tag. You will call it from every callback.

    You should seeA single TAG constant you can grep for.
  3. Log the activity callbacks

    Override onCreate, onStart, onResume, onPause, onStop, onDestroy and log each one. In Compose, the activity is still the lifecycle owner; the composables follow it.

    You should seeonCreate, onStart, onResume appear in order at launch.
  4. The logging is one line per callback:

    class MainActivity : ComponentActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            Log.i("LifecycleDemo", "onCreate")
            setContent { /* ... */ }
        }
     
        override fun onStart() { super.onStart(); Log.i("LifecycleDemo", "onStart") }
        override fun onResume() { super.onResume(); Log.i("LifecycleDemo", "onResume") }
        override fun onPause() { Log.i("LifecycleDemo", "onPause"); super.onPause() }
        override fun onStop() { Log.i("LifecycleDemo", "onStop"); super.onStop() }
        override fun onDestroy() { Log.i("LifecycleDemo", "onDestroy"); super.onDestroy() }
    }
  5. Add the counter

    Hold the counter in a rememberSaveable so it survives a configuration change. A plain remember does not, which is the point of the next step.

    You should seeThe counter increments when you tap.
  6. Watch a rotation

    Rotate the emulator. Filter logcat by your tag and read the sequence: the activity is destroyed and recreated, and rememberSaveable restores the counter from the saved instance state.

    You should seeA destroy/create pair, then start and resume again, with the counter preserved.
  7. Break it deliberately

    Change rememberSaveable to remember and rotate again. The counter resets, because a plain remember is scoped to the composition, not to the saved state.

    You should seeThe counter resets on rotation.
  8. Put the counter in a ViewModel

    Move the counter into a ViewModel. Rotating no longer loses it, because the ViewModel outlives the activity instance. Compare this with rememberSaveable: both survive a rotation, and they fail differently when the process is killed.

    You should seeThe counter survives a rotation without saved state.
  9. The two mechanisms in code:

    // Survives a configuration change, not process death.
    val counter by viewModel.count.collectAsStateWithLifecycle()
     
    // Survives both, because it is written to the saved instance state.
    var saved by rememberSaveable { mutableIntStateOf(0) }
  10. Kill the process

    Use the emulator's device state or adb shell am kill <package> to kill the process while the app is backgrounded, then reopen it. This is the difference between a configuration change and process death, and it is the reason saved state exists.

    You should seeThe ViewModel value is lost; the saved-state value is restored.
Watch the lifecycle
adb logcat -c
adb logcat -s LifecycleDemo
adb shell am start -W -n com.example.lifecycledemo/.MainActivity
adb shell input keyevent KEYCODE_HOME
adb shell am start -W -n com.example.lifecycledemo/.MainActivity
Example output
Illustrative output — your timestamps and PIDs differ.

Verification#

You should be able to answer three questions from the log alone:

  • What is the order of callbacks on a cold launch?
  • Which callbacks run when the app goes to the background, and which do not?
  • What happens to the activity instance on a rotation?

If the answers are not visible in the log, add logging to the composables' lifecycle as well and compare. Compose's LifecycleEventEffect or a DisposableEffect shows where composition differs from the activity.

What you learned#

  • The lifecycle is a contract, not a suggestion: the system calls the callbacks in a defined order and your code must survive them.
  • Configuration changes recreate the activity. Saved state and ViewModels are two different answers to that, with different lifetimes.
  • Process death is a third case. Saved state survives it; a ViewModel does not.
  • Logging is the cheapest observability tool you have. A tag and a filter turn an invisible contract into a sequence you can read.

Read Activity lifecycle for the full callback map, and Lab 4 — logcat for the filtering you just used.

Extend it#

  1. Add a second activity and log both lifecycles during a transition. You will see the ordering between the outgoing and incoming activity, which is the part people get wrong.
  2. Add a ViewModel with a saved-state handle so the value survives both a rotation and process death, and compare the two mechanisms.
  3. Trigger a configuration change without rotating using adb shell cmd activity or by changing the font scale in Settings, and compare the callback sequence.

Sources#

Sources

Every version number, API level, class name and date on this page is traced to one of these. Pages are re-verified against them; last_verified above says when.

  1. docsThe activity lifecycledeveloper.android.comaccessed 2026-10-27↩
  2. docs活動簡介 | App architecturedeveloper.android.comaccessed 2026-10-27↩
  3. docsAndroid Debug Bridge (adb)developer.android.comaccessed 2026-10-27↩
  4. docsProcesses and app lifecycledeveloper.android.comaccessed 2026-10-27↩
  5. docsLifecycle of composablesdeveloper.android.comaccessed 2026-10-27↩