Live coding · 14 min
Mobile live coding interview: what to say while you type
How a mobile live coding round is scored, a 45-minute plan, what to say at each stage, a worked Swift example, and how to recover when you stall.
Android · 12 min read
What an Android coding interview asks: the practical tasks to prepare, the algorithm round in Kotlin, and what is graded beyond a screen that works.
This page is for Android engineers with an Android coding interview on the schedule, live or take-home, who want to know what to build in preparation and how the result is graded. You get the two formats and how to tell them apart, the practical tasks worth rehearsing, what the interviewer grades beyond “it runs”, a worked search screen in Kotlin with its test, and the Android traps that cost points in the last ten minutes.
How to behave while you type, narration, the plan and recovery when you stall, is covered in Mobile live coding interview. This page is about what you build.
Android coding rounds come in two shapes. An algorithm round is a data structure problem you solve in Kotlin, often in a shared editor with no Android SDK. A practical round is a small app or screen, built in Android Studio or on a starter project the company gives you. They are prepared for differently, so ask the recruiter four things:
Nobody is scored down for asking. Candidates who ask walk in with the right project already open.
A platform exercise is usually a small version of something every app has: build a list screen, fetch and show data, add search. Build each of these once, alone, against a timer, before the interview:
| Task | What it really tests |
|---|---|
| A paged list from an API | Where the data lives, loading and error states, what happens on refresh while a page is loading |
| Search with debounce | Cancelling stale requests, keeping the query across rotation, testing time without real delays |
| An offline cache for the list | Room as the source of truth, the network updating the database rather than the screen |
| A detail screen with a form | Saved state, process death, one-time events such as “saved” |
None of these is hard for an experienced engineer. That is the point. The round is not checking whether you can build a list. It is checking the decisions you make while building it under a clock.
Correct final code is one line on the scorecard, and not the heaviest. For a practical Android task, I grade in this order:
| What I note | Strong | Weak |
|---|---|---|
| The model first | A UI state type and a repository interface before any layout | Starts with the layout and discovers the state later |
| Ownership | One ViewModel owns screen state, the UI renders it | State split between composables, fragments and callbacks |
| Cancellation | A new query cancels the old request, and says so | Stale results arrive after new ones |
| Lifecycle | Rotation and backgrounding considered without being asked | “It works on my emulator” |
| Error state | The network fails and the screen says something useful | Only the happy path |
| Tests | One test on the ViewModel, with controlled time | “I would add tests later” |
The grade is often set in the first ten minutes, by how you shape the state and whether you mention cancellation. The UI is rarely what decides it.
Prompt: “Build a search screen. Results come from a repository. Do not hit the API on every keystroke.”
The plan, said out loud in three sentences: “The ViewModel owns the query, kept in SavedStateHandle so it survives process death. Results are derived from the query with a debounce and flatMapLatest, so a new query cancels the old search. I will test the debounce with virtual time rather than waiting.”
class SearchViewModel(
private val handle: SavedStateHandle,
private val repository: SearchRepository,
) : ViewModel() {
val query: StateFlow<String> = handle.getStateFlow("query", "")
@OptIn(FlowPreview::class, ExperimentalCoroutinesApi::class)
val results: StateFlow<SearchUiState> = query
.debounce(300)
.flatMapLatest { q ->
if (q.isBlank()) flowOf(SearchUiState.Idle)
else flow {
emit(SearchUiState.Loading)
emit(SearchUiState.Results(repository.search(q)))
}.catch { emit(SearchUiState.Error) }
}
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), SearchUiState.Idle)
fun onQueryChange(value: String) { handle["query"] = value }
}And the test, which is the part that gets dropped when time runs short:
@Test fun `only the last query is searched`() = runTest {
Dispatchers.setMain(StandardTestDispatcher(testScheduler))
try {
val repository = FakeSearchRepository()
val vm = SearchViewModel(SavedStateHandle(), repository)
backgroundScope.launch { vm.results.collect {} } // a subscriber starts the upstream
runCurrent()
vm.onQueryChange("ko"); vm.onQueryChange("kot"); vm.onQueryChange("kotlin")
advanceTimeBy(301) // virtual time crosses the debounce
runCurrent()
assertEquals(listOf("kotlin"), repository.searched)
assertTrue(vm.results.value is SearchUiState.Results)
} finally {
Dispatchers.resetMain()
}
}What the interviewer asks next, and what a strong answer says:
flatMapLatest and not flatMapConcat?” A new query should cancel the search for the old one. With flatMapConcat, a slow search for an earlier query would run to the end first and hold up the one the user is waiting for.WhileSubscribed(5_000) outlasts the rotation. Say both before they rotate it.catch is inside flatMapLatest, so one failed search shows an error and the next query still works. Put it outside and the whole stream ends after the first failure. That placement is the detail I would listen for.If the round is an algorithm problem, the Android SDK is irrelevant and Kotlin is an advantage if you know the standard library. Have these ready without thinking: ArrayDeque for queues and stacks, HashMap and HashSet, sortedWith(compareBy(...)), groupingBy { }.eachCount(), buildList { }, and IntArray when boxing would matter.
Two traps specific to Kotlin. First, !! to silence the compiler: an interviewer reads it as “I have not thought about this case”. Handle the null or say why it cannot happen. Second, asSequence() by habit. On a small input with one map, a sequence saves nothing and adds overhead. Say when you would use one: a long pipeline over a large input, or an early first { } that can skip most elements.
Pin the contract before you type. “Merge overlapping availability windows” leaves open whether [9, 10) and [10, 11) become one window, and your loop depends on the answer. Only ask what changes the algorithm, the data shape or the pass condition, then repeat the agreed contract in one sentence. When you test, claim exactly what you ran: if three examples passed, say three examples passed, not that edge cases are covered. In a comparator use compareValues or compareBy; a.start - b.start overflows once the values are large enough.
State the complexity before you are asked, and name the case where it breaks: “Linear in the number of items, but the sort makes it n log n, which is fine up to a size the phone will ever see.”
A take-home is graded by someone who cannot ask you why. So the README has to answer it: what you built, what you left out on purpose, what you would do next, and how to run the tests. A take-home with no tests and a clever architecture usually scores below a simple one with a clear README and three tests that matter.
A live round is graded on what the interviewer could see of your thinking. The same code, written in silence, scores lower. The live coding guide has the minute-by-minute plan.
lifecycleScope.launch { flow.collect { } } without repeatOnLifecycle keeps collecting in the background. In Compose, collectAsStateWithLifecycle.Dispatchers.IO inside the repository makes the test nondeterministic. Inject it.There is no live coding book for Android in this catalogue. Share Your Screen covers the iOS round only. For Android, the platform reasoning these tasks test is covered in The Senior Signal, and Android interview books compares it with the other titles.
Whichever you pick, answer out loud and time yourself. Saying the answer is the part a page cannot do for you, and it is the part the round scores.

Live coding · 14 min
How a mobile live coding round is scored, a 45-minute plan, what to say at each stage, a worked Swift example, and how to recover when you stall.

Android · 16 min
Android technical interview questions and answers: lifecycle, process death, coroutines, data, security and testing, with the follow-up to each.

Android · 13 min
Kotlin interview questions as Android loops ask them: null safety, coroutines, cancellation, Flow, sealed types and generics, with each follow-up.