---
skill: Mobile
title: Android Fundamentals
type: Concept guide
summary: Kotlin, the lifecycle that actually bites, and how Compose recomposes.
owner: Developer D
updated_by: Developer D
updated: 2026-09-29
---

# Android Fundamentals

## Kotlin essentials

- **Null safety** is in the type system. `String?` and `String` are different
  types, and the compiler will hold you to it.
- **Data classes** give you `equals`, `hashCode`, `copy` and destructuring.
- **Sealed classes** model a closed set of states — perfect for UI state.

```kotlin
sealed interface SkillUiState {
    data object Loading : SkillUiState
    data class Ready(val skills: List<Skill>) : SkillUiState
    data class Failed(val message: String) : SkillUiState
}
```

## The lifecycle that actually bites

Rotation, dark mode, language change and low memory can all destroy and recreate
your Activity. Anything held only in the Activity is gone.

- Survives recreation: `ViewModel`.
- Survives process death: `SavedStateHandle`, or persisted storage.
- Survives nothing: a property on the Activity.

## Compose and recomposition

Compose re-runs composable functions when the state they read changes. This means:

- A composable must be **side-effect free** — it can run many times.
- Read state as late as possible, so less gets recomposed.
- Hoist state: a composable that takes a value and a callback is testable and
  reusable; one that owns its own state is neither.

```kotlin
@Composable
fun LevelChip(level: Int, modifier: Modifier = Modifier) {
    Text(
        text = "L$level",
        style = MaterialTheme.typography.labelSmall,
        modifier = modifier
            .background(MaterialTheme.colorScheme.surfaceVariant, CircleShape)
            .padding(horizontal = 8.dp, vertical = 2.dp),
    )
}
```

## Coroutines

- Structured concurrency: work is scoped, and cancelling the scope cancels the
  work. Use `viewModelScope`.
- `Flow` is a stream. `StateFlow` always has a current value — that is what a
  screen wants.
- Never block the main thread. Use `withContext(Dispatchers.IO)` for disk and
  network.
