Android interviews focus on Kotlin idioms, coroutines, and the platform lifecycle — most senior questions are really asking whether you understand that your process can be killed at any moment. Below are the questions asked most often, each with a model answer. Junior: core theory, definitions, and simple practical cases.
1
How does Kotlin null safety work, and when is a platform type dangerous?
Answer
Kotlin splits every type into nullable (String?) and non-nullable (String), and the compiler refuses to dereference a nullable value without a check, so NullPointerException largely disappears. Platform types arise at the Java boundary: Kotlin does not know whether a Java method can return null, so it trusts you. That is where NPEs still come from — annotate Java APIs or treat their results as nullable at the call site.
2
What do data classes and sealed classes give you?
Answer
A data class generates equals, hashCode, toString, copy and destructuring from the primary constructor, which makes it the right tool for values you compare and copy — API models, UI state. A sealed class restricts its subclasses to a known set, so a when over it is exhaustive and the compiler flags any branch you forget. Together they model UI state cleanly: a sealed interface for Loading, Content, Error, with data classes carrying the payload.
3
What is structured concurrency in coroutines, and what does a scope do?
Answer
Structured concurrency means every coroutine belongs to a scope and a parent job, so cancelling the parent cancels all children and the parent will not complete until they do. That is what prevents the leaked background work you get from raw threads. On Android, viewModelScope is cancelled when the ViewModel clears and lifecycleScope when the lifecycle ends, so work stops when its result can no longer be used.
4
Explain the Dispatchers and which one you use for what.
Answer
Dispatchers.Main runs on the UI thread and is where you touch views. Dispatchers.IO is a large elastic pool for blocking work — disk, network, database — because those threads spend their time waiting. Dispatchers.Default is sized to the CPU count and is for actual computation like parsing or sorting. Putting a blocking call on Default starves the pool, which is the most common dispatcher mistake.
5
What is the difference between Flow, StateFlow and LiveData?
Answer
Flow is a cold asynchronous stream: it starts producing when collected, and each collector gets its own execution. StateFlow is hot and always holds exactly one current value, which makes it the natural fit for UI state — new collectors immediately get the latest state. LiveData is the older lifecycle-aware holder; StateFlow plus repeatOnLifecycle covers the same need with the rest of the coroutines toolkit, so new code generally prefers it.
6
Why does a configuration change recreate the Activity, and how do you survive it?
Answer
Rotation, dark mode, language and window size changes destroy and recreate the Activity so it can load resources for the new configuration. State that must survive belongs in a ViewModel, which outlives the recreation. State that must also survive process death goes into SavedStateHandle, because the system can kill your process in the background and restore the task later — testing that path with "Don't keep activities" is what separates a robust app from one that loses the user's input.
7
What triggers recomposition in Jetpack Compose, and what makes it slow?
Answer
Compose re-runs a composable when a State it reads changes, and it skips composables whose parameters are equal and stable. Slowness comes from unstable parameters — a plain List or a lambda capturing a changing value — which defeat skipping and re-run large subtrees. The fixes are hoisting state to the lowest common owner, using immutable collections or @Immutable annotations, and deferring reads with lambdas so only the layout or draw phase re-runs.
8
Why use dependency injection with Hilt instead of constructing objects directly?
Answer
DI removes the need for a class to know how to build its dependencies, which makes it testable and keeps wiring in one place instead of scattered singletons. Hilt generates the Dagger graph and ties component lifetimes to Android ones — a @Singleton lives with the application, a @ViewModelScoped binding with the ViewModel. The practical payoff is swapping a real repository for a fake in tests without touching production code.
9
How do you structure a screen in clean architecture terms?
Answer
The UI layer holds Compose or Views plus a ViewModel that exposes immutable state and receives events. The domain layer holds use cases and pure business rules with no Android imports, which is what makes it testable with plain JUnit. The data layer holds repositories that decide between Room and Retrofit and map DTOs to domain models. The rule that matters is dependency direction: domain knows nothing about data or UI.
🦎
Reading answers is not enough
In a real interview you speak under pressure. Cam asks these same questions, scores every answer, and shows exactly what to fix.
Practice a Junior Android (Kotlin) interview →Free · 3 interviews per month