Pitfalls

Stale Dependency Snippets

Android snippets age fast. AGP, Kotlin, Compose BOM, KSP, Room, WorkManager, lifecycle, activity-compose, and navigation versions must be verified when implementing.

Do this instead:

1. Check the generated Android Studio project.
2. Check official AndroidX release pages or official setup docs.
3. Update version catalogs intentionally.
4. Record the source and date in the project note.

Compose Recomposition Loops

Do not write to state while composing. Handle events in callbacks and side effects in appropriate effect APIs.

Bad shape:

@Composable
fun Total(total: Int) {
    var copied by remember { mutableStateOf(false) }
    copied = total > 0
    Text(total.toString())
}

Better shape:

@Composable
fun Total(total: Int) {
    val hasValue = total > 0
    Text(if (hasValue) total.toString() else "No transactions")
}

Unstable Lazy Lists

Always provide stable keys for persisted items:

LazyColumn {
    items(
        items = transactions,
        key = { transaction -> transaction.id },
    ) { transaction ->
        TransactionRow(transaction)
    }
}

Without keys, list state and recomposition can behave badly when rows are inserted, removed, or reordered.

ViewModel In Previews

Previews should render stateless composables with fake state. Do not make previews construct real ViewModel, Room, network, or WorkManager dependencies.

Room Migration Data Loss

fallbackToDestructiveMigration() is not a development shortcut for user data apps. It is a data deletion policy. Treat it as unacceptable for finance, ledger, tracker, and local-first apps unless the feature is explicitly disposable.

WorkManager As A Hammer

WorkManager is for reliable persistent work. It is not for every coroutine, every screen refresh, or every button click. If losing the process can safely cancel the work, use coroutines tied to the relevant scope.

Background And OEM Quirks

WorkManager follows Android power-saving behavior, but budget devices and OEM battery settings can still change real-world timing. Test on the target device class before promising exact timing.

Play Restricted Permissions

Do not add READ_SMS, Call Log, Accessibility, background location, or broad storage permissions because they are convenient. Policy-gated permissions need a core-functionality argument, declaration, privacy copy, user-facing rationale, and fallback mode.

Signing Secrets

Never commit keystores, upload keys, keystore.properties, passwords, Play service account keys, or screenshots that expose private signing details.

Target API Drift

Target API requirements change. Release work must include a fresh target API check and Play Console compatibility check.