Full Android Technical Mock Pack
Complete technical mock interview round with model answers and self-scoring rubric
Open interactive version (quiz + challenge)Real-world analogy
What is it?
A full technical mock interview pack for senior Android engineers, covering Kotlin, Coroutines/Flow, Android components, Jetpack Compose, and architecture. Each question includes a model answer with a 1–4 self-scoring rubric. This pack simulates a real technical panel round and gives structured feedback so you know exactly what to study before the real interview.
Real-world relevance
Senior Android interviews at companies like Wise, Klarna, Spotify, N26, and Grab typically include 2–3 technical rounds: (1) a Kotlin/language fundamentals screen, (2) a systems/architecture deep-dive, and (3) a practical coding or review session. This mock pack covers the content of rounds 1 and 2. Candidates who complete 3 full mock rounds before interviewing report significantly higher confidence and offer rates.
Key points
- Mock interview discipline — Treat this as a real interview. No notes. No IDE. Time yourself on each question — technical questions: 5–8 minutes each. Architecture questions: 10–15 minutes. Score yourself immediately after each answer before reading the model answer.
- Self-scoring rubric (1–4 scale) — 1 = Blank or fundamentally wrong. 2 = Partial — got the concept but missed key details. 3 = Solid — correct, complete, one or two gaps. 4 = Exceptional — correct, complete, with real-world nuance, edge cases, and production experience. Aim for 3+ on all questions, 4 on your strongest areas.
- Kotlin fundamentals mock — Core questions: coroutines vs threads, suspend function internals, sealed classes vs enums, inline functions and reified generics, data class copy semantics, object vs companion object, extension functions vs member functions.
- Coroutines and Flow mock — Core questions: structured concurrency, CoroutineScope vs GlobalScope, StateFlow vs SharedFlow vs LiveData, Flow operators (map/filter/flatMapLatest/debounce), exception handling in flows, combining flows, cancellation behavior.
- Android components mock — Core questions: Activity/Fragment lifecycle gotchas, ViewModel saved state, WorkManager vs AlarmManager vs Foreground Service, BroadcastReceiver types (ordered vs normal vs local), ContentProvider threading model.
- Compose mock — Core questions: recomposition triggers and stability, remember vs rememberSaveable vs derivedStateOf, side effects (LaunchedEffect vs SideEffect vs DisposableEffect), Compose vs View interop, custom layouts, performance profiling in Compose.
- Architecture mock — Core questions: Clean Architecture layer responsibilities and dependency direction, MVI vs MVVM state management tradeoffs, repository pattern with multiple data sources, use case design, module boundaries in multi-module apps.
- Performance mock — Core questions: diagnosing ANR, profiling with Android Studio (CPU, Memory, Network profilers), frame rate analysis with Perfetto, APK size reduction strategies, bitmap memory management.
- Testing mock — Core questions: unit vs integration vs UI test scope, mocking strategies with MockK, Turbine for Flow testing, testing ViewModel with TestCoroutineScheduler, UI test with Espresso vs Compose test APIs.
- Security mock — Core questions: certificate pinning implementation and bypass risks, EncryptedSharedPreferences vs Keystore, ProGuard/R8 rules for security, SafetyNet/Play Integrity API use cases, root detection strategies.
- Model answer format — Every model answer in this pack follows: Definition (one sentence), How it works (mechanism), When to use it (decision criteria), Real-world example (from production), Edge case or gotcha (what trips up candidates). Use this same structure in your real answers.
- Scoring your mock — After completing all 15+ questions: tally your scores, identify your weakest category (lowest average score), go back to the relevant lesson in this course and review, then repeat the mock questions in that category 48 hours later. Spaced repetition beats cramming.
Code example
// MOCK ROUND — ANSWER THESE WITHOUT LOOKING AT MODEL ANSWERS
// ============================================================
// SECTION 1: KOTLIN FUNDAMENTALS (Score each /4)
// ============================================================
// Q1: What is structured concurrency and why does it matter?
// [ANSWER SPACE — write or say your answer before reading below]
// MODEL ANSWER (Score /4):
// Structured concurrency means coroutines are scoped to their parent.
// When a parent scope is cancelled, all child coroutines are cancelled.
// When all children complete, the parent scope completes.
// This prevents coroutine leaks — unlike Thread or GlobalScope which
// have no automatic cleanup on lifecycle events.
// Real world: ViewModelScope cancels all launched coroutines when the
// ViewModel is cleared, preventing updates to destroyed UI.
// Gotcha: GlobalScope breaks structured concurrency — avoid it except
// for truly app-lifetime operations.
// ------------------------------------------------------------
// Q2: Explain StateFlow vs SharedFlow. When do you use each?
// [ANSWER SPACE]
// MODEL ANSWER:
// StateFlow: always has a current value (initial value required),
// replays the latest value to new collectors, conflates rapid updates.
// Use for: UI state (uiState: StateFlow<UiState>).
// SharedFlow: no initial value, configurable replay cache (0 to N),
// configurable buffer overflow strategy.
// Use for: one-shot events (navigation, snackbars) where you do not
// want new collectors to receive old events.
// Gotcha: StateFlow.value access is not safe across threads in general —
// always collect from a coroutine, not from a callback.
// ------------------------------------------------------------
// Q3: What triggers recomposition in Jetpack Compose?
// [ANSWER SPACE]
// MODEL ANSWER:
// Recomposition triggers when state read inside a composable changes.
// Compose tracks state reads at the composable level using snapshot state.
// Key rules:
// - Only composables that READ the changed state recompose
// - Composables are skippable if all parameters are stable and unchanged
// - Unstable classes (List, non-data classes) force recomposition even
// when the content is the same
// Gotcha: Lambdas that capture mutable state or are not remembered cause
// unnecessary recompositions. Use remember { derivedStateOf { ... } }
// to only recompose when computed value changes.
// ============================================================
// SECTION 2: ANDROID ARCHITECTURE (Score each /4)
// ============================================================
// Q4: Explain Clean Architecture dependency direction.
// [ANSWER SPACE]
// MODEL ANSWER:
// Dependencies point INWARD only:
// UI layer -> Domain layer <- Data layer
// Domain layer (use cases, entities) has NO Android dependencies.
// Data layer implements domain interfaces (repository pattern).
// UI layer depends on domain, never on data directly.
// Why: domain layer can be unit tested with pure JVM, no Android mocks.
// Real world: a UseCase that calls repository.getTransactions() is
// testable without a database or network by injecting a fake repository.
// Gotcha: putting Android Context or Room entities in the domain layer
// violates the dependency rule and makes domain untestable.
// ------------------------------------------------------------
// Q5: How do you handle offline-first data synchronization?
// [ANSWER SPACE]
// MODEL ANSWER:
// Pattern: Single Source of Truth (SSOT) — Room is the only source
// the UI reads from. Network data flows: API -> Room -> UI via Flow.
// Implementation:
// 1. Repository.getItems() returns Flow<List<Item>> from Room
// 2. A background sync (WorkManager) fetches from API and writes to Room
// 3. Room emits updates automatically, UI reacts
// Conflict resolution: last-write-wins or timestamp-based or server-wins.
// Edge case: deletions — use soft delete (isDeleted flag) + sync timestamp
// rather than hard deletes, to avoid sync conflicts.
// ============================================================
// SELF-SCORING:
// After answering all questions:
// - Score 1-4 on each question
// - Average by category
// - Weakest category = top priority before real interview
// ============================================================Line-by-line walkthrough
- 1. Mock discipline: no notes, no IDE, timed — simulate real interview pressure to build the muscle memory you need on interview day.
- 2. Rubric 1 = fundamentally wrong or blank: immediately review the concept in the relevant lesson before continuing.
- 3. Rubric 2 = partial: you understand the surface, not the depth — study the mechanism and the edge cases.
- 4. Rubric 3 = solid: one or two gaps — these are the gaps interviewers will probe. Practice specifically for the gap.
- 5. Rubric 4 = exceptional: correct, complete, production nuance, edge case awareness. This is the senior bar.
- 6. Kotlin section covers: structured concurrency, coroutine mechanics, StateFlow vs SharedFlow, sealed classes, inline/reified, data class semantics.
- 7. Architecture section covers: Clean Architecture dependency direction, offline-first SSOT pattern, repository design, use case boundaries.
- 8. Compose section covers: recomposition triggers, stability, remember vs rememberSaveable vs derivedStateOf, side effects, performance.
- 9. Model answer format: Definition + Mechanism + When to use + Real-world example + Edge case/gotcha — use this structure in real interviews.
- 10. Scoring workflow: answer all questions, score each, average by category, target weakest category for focused review.
- 11. Spaced repetition: repeat weak-category questions 48 hours later, not immediately — spacing creates durable memory.
- 12. 3 full mock rounds before a real senior interview is the recommended minimum for confident performance.
Spot the bug
// KOTLIN BUG — FIND AND FIX:
class UserRepository(private val api: UserApi) {
suspend fun getUser(id: String): User {
return GlobalScope.async {
api.fetchUser(id)
}.await()
}
fun observeUsers(): Flow<List<User>> {
return flow {
while (true) {
emit(api.fetchAllUsers())
delay(30_000)
}
}
}
}Need a hint?
Show answer
Explain like I'm 5
Fun fact
Hands-on challenge
More resources
- Kotlin Coroutines — Official Documentation (Kotlin)
- Jetpack Compose — Performance Guide (Android Developers)
- Android Architecture — Official Guide (Android Developers)
- Perfetto Tracing Tool (Perfetto)
- Turbine — Flow Testing Library (Cash App / GitHub)