← Mobile app development with Android, Flutter and React Native

Lesson 2 of 4

Android essentials: lifecycle, Compose and architecture

2 min read

Activity lifecycle

onCreate → onStart → onResume (visible and interactive) → onPause (partly hidden) → onStop (not visible) → onDestroy.

  • Configuration changes (rotation, dark mode, language) destroy and recreate the activity by default. State held only in the activity is lost, which is why we use a ViewModel (survives configuration changes) and SavedStateHandle/rememberSaveable (survives process death).
  • Release resources in onStop or with lifecycle-aware components; start them in onStart.

Other components: Fragments (reusable UI portions with their own lifecycle), Services (background work), Broadcast receivers (system events), Content providers (sharing data between apps). Long background work belongs in WorkManager (guaranteed, battery-aware execution).

Jetpack Compose (modern Android UI)

Compose is declarative, like React: UI is a function of state.

kotlin
@Composable
fun JobList(viewModel: JobsViewModel = viewModel()) {
    val state by viewModel.state.collectAsStateWithLifecycle()
    when (val s = state) {
        is JobsState.Loading -> CircularProgressIndicator()
        is JobsState.Error -> Text("Couldn't load jobs. Pull to retry.")
        is JobsState.Ready -> LazyColumn {
            items(s.jobs, key = { it.id }) { job -> JobRow(job, onApply = { viewModel.apply(job.id) }) }
        }
    }
}

Key ideas: recomposition when state changes, remember to keep values across recompositions, state hoisting (stateless composables receiving state and callbacks), LazyColumn for long lists (like RecyclerView), and side effects with LaunchedEffect.

text
UI (Compose / Views)  ←  observes state  ←  ViewModel  →  Repository  →  Remote API (Retrofit)
                                                                    →  Local DB (Room)
  • ViewModel holds UI state (StateFlow) and survives rotation.
  • Repository is the single source of truth, deciding between network and cache.
  • Coroutines for async work: viewModelScope.launch { }; Dispatchers.IO for disk and network; structured concurrency cancels work when the screen goes away.
  • Dependency injection with Hilt.
  • Room for local SQL storage; DataStore for small key-value settings.

Common Android interview questions

  • Activity vs Fragment; lifecycle callbacks in order.
  • How to survive rotation (ViewModel) and process death (SavedState).
  • What causes an ANR (work over ~5 s on the main thread) and how to avoid it.
  • Memory leaks: holding an Activity context in a long-lived object; fix with application context and lifecycle-aware observers.
  • LiveData vs StateFlow; coroutines vs threads.

Check yourself

  • Why does rotating the phone lose state in a naive app, and how do you fix it?
  • What does the Repository pattern give you?

Sign up free to save your progress.