Skip to content

Android App Development Mock Interview: 20 Questions in 50 Minutes

Four rounds that copy a real interview. Answer aloud, then check the model answers.

Mock interview format

  1. Warm-up · 5 minutes — 4 questions
  2. Technical · 20 minutes — 7 questions
  3. Scenario · 15 minutes — 5 questions
  4. HR & behavioural · 10 minutes — 4 questions

Tip: record yourself and listen back. Most people talk too fast and skip the key idea.

Mock progressStart practicing
3 QUESTIONS FREESign up to unlock the full question bank and track your progress.Unlock every question and answer, then continue practising company-wise and package-wise.
3 questions free Unlock the rest in seconds
01

What types of tests do you write for an Android app?

Save to ▾
Show answer
Local unit tests on the JVM cover ViewModels, use cases, repositories and mappers with JUnit, fakes and coroutine test tools; they are fast and most numerous. Instrumented tests run on a device or emulator for Room, Compose UI and integration flows. End-to-end UI tests check critical journeys like login and checkout. Screenshot tests catch visual regressions. Follow the testing pyramid: many unit tests, fewer UI tests.
02

Why does the order of modifiers matter?

Warm-upJetpack ComposeEasy
Save to ▾
Show answer
Modifiers are applied in a chain from left to right, each wrapping the next. Modifier.padding(16.dp).background(Color.Red) adds padding outside the red area, while background first then padding colours the padding too. Similarly, clickable before padding makes the whole padded area clickable. Thinking of each modifier as wrapping the content after it helps predict layout, size and touch target behaviour.
03

What is dependency injection and why use Hilt?

Save to ▾
Show answer
Dependency injection means classes receive their dependencies from outside rather than creating them, making code testable and loosely coupled. Hilt, built on Dagger, is Jetpack's recommended DI library. It generates code at compile time, provides standard components tied to Android lifecycles (SingletonComponent, ActivityRetainedComponent, ViewModelComponent), and integrates with ViewModels via @HiltViewModel. Errors appear at compile time rather than runtime.
04

What is recomposition?

Warm-upJetpack ComposeEasy
Save to ▾
Show answer
Recomposition is Compose re-running composable functions whose inputs or read state changed, to update the UI. Compose tries to skip composables whose parameters are stable and unchanged. Composables can run often and in any order, so they must be side-effect free and fast; do not make network calls or write to variables inside them. Use Layout Inspector recomposition counts to find composables recomposing more than expected.
05

Write a Compose UI test that checks an error appears when login is clicked with an empty email.

TechnicalJetpack ComposeMedium
Save to ▾
Show answer
@get:Rule val rule = createComposeRule() @Test fun showsErrorForEmptyEmail() { rule.setContent { var state by remember { mutableStateOf(LoginState()) } LoginScreen( state = state, onLogin = { state = state.copy(error = "Email required") } ) } rule.onNodeWithText("Login").performClick() rule.onNodeWithText("Email required").assertIsDisplayed() }
06

Write a Gradle configuration for release signing and minification using environment variables.

Save to ▾
Show answer
android { signingConfigs { create("release") { storeFile = file(System.getenv("KEYSTORE_PATH") ?: "release.jks") storePassword = System.getenv("KEYSTORE_PASSWORD") keyAlias = System.getenv("KEY_ALIAS") keyPassword = System.getenv("KEY_PASSWORD") } } buildTypes { release { isMinifyEnabled = true isShrinkResources = true proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") signingConfig = signingConfigs.getByName("release") } } }
07

How do you model API results and errors cleanly for the UI?

TechnicalNetworking and APIsMedium
Save to ▾
Show answer
Map transport-level outcomes into a sealed result type in the data layer, for example Success(data), HttpError(code, message) and NetworkError. Catch IOException for connectivity, HttpException for non-2xx codes, and serialization exceptions for bad payloads, and never catch CancellationException. The ViewModel converts these into user-friendly UiState messages. Keep DTOs separate from domain models so API changes do not ripple through the UI.
08

How do you implement theming with Material 3 in Compose?

TechnicalJetpack ComposeMedium
Save to ▾
Show answer
Wrap the app in a MaterialTheme with a ColorScheme, Typography and Shapes. Use lightColorScheme and darkColorScheme, pick based on isSystemInDarkTheme(), and use dynamicLightColorScheme or dynamicDarkColorScheme on Android 12 and above for Material You colours. Components read MaterialTheme.colorScheme.primary and similar roles, so avoid hardcoding colours. Extend the theme with a custom CompositionLocal for brand-specific tokens.
09

Write a delegated property that logs whenever a value changes.

TechnicalKotlin FundamentalsMedium
Save to ▾
Show answer
import kotlin.properties.Delegates class Settings { var theme: String by Delegates.observable("light") { prop, old, new -> println("${prop.name} changed from $old to $new") } } // Use Delegates.vetoable if you need to reject a change // by returning false from the lambda.
10

What conflict strategies does Room offer for inserts?

Save to ▾
Show answer
@Insert(onConflict = ...) supports REPLACE, which deletes the old row and inserts the new one; IGNORE, which skips the insert; ABORT, the default, which rolls back the transaction; and others. REPLACE can trigger cascading deletes on foreign keys because it deletes first. @Upsert, added in Room 2.5, inserts or updates without deleting, making it safer for syncing server data into local tables.
11

What is the difference between @Provides and @Binds in Hilt?

Save to ▾
Show answer
@Provides is used in a module function that constructs and returns an object, needed for third-party classes like Retrofit or Room that you cannot annotate with @Inject. @Binds is used on an abstract function in an abstract module to tell Hilt which implementation to use for an interface, when the implementation already has an @Inject constructor. @Binds generates less code and is slightly more efficient.
12

The APK size grew to 120 MB and installs from small towns are dropping. How do you reduce it?

Save to ▾
Show answer
Analyse the build with APK Analyzer. Publish as an App Bundle so users get only their density, language and ABI. Enable R8 and resource shrinking, convert images to WebP or vectors, remove unused libraries and duplicate dependencies, and move large optional features or assets to Play Feature Delivery or Play Asset Delivery. Avoid bundling all native libraries for every ABI. Track size in CI.
13

A Compose list scrolls with jank on low-end phones. How do you investigate and fix it?

ScenarioJetpack ComposeHard
Save to ▾
Show answer
Test a release build with R8, since debug builds are much slower. Use Layout Inspector recomposition counts and a system trace or Macrobenchmark to find hot spots. Common fixes: add keys and contentType, avoid heavy work or sorting inside composables, move computation to the ViewModel, use derivedStateOf for scroll-based state, defer state reads with lambda modifiers like offset { }, load images at the right size with Coil, and add a Baseline Profile.
14

Your team is migrating a Java Android app to Kotlin. How would you plan it?

ScenarioKotlin FundamentalsMedium
Save to ▾
Show answer
Kotlin and Java interoperate, so migrate gradually rather than all at once. Start with new features in Kotlin, then convert leaf classes like models and utilities, writing tests before converting. Add nullability annotations to Java code so Kotlin sees correct types. Review auto-converted code because it often overuses !!. Track progress per module and agree on style rules with ktlint or detekt so the codebase stays consistent.
15

Users on slow 2G and 3G networks in small towns report the app keeps failing. How do you improve it?

ScenarioNetworking and APIsMedium
Save to ▾
Show answer
Set reasonable connect and read timeouts, retry idempotent requests with exponential backoff, and cache responses so screens show something offline. Reduce payload size with gzip, pagination and fields filtering, and load images in smaller sizes with placeholders. Show clear offline and retry states instead of generic errors. Test with the emulator network throttling and real devices on poor connections, and track failure rates by network type.
16

Product wants a feature flag to turn a new checkout on or off without releasing an update. How do you design it?

Save to ▾
Show answer
Use a remote config service with defaults bundled in the app, wrapped in a FeatureFlags interface injected via Hilt. Fetch and cache values at startup with a sensible timeout, and read the flag at navigation decision points rather than deep inside UI code. Keep both checkout paths tested, log which variant users see for analytics, and plan to remove the old path and the flag after rollout.
17

Tell me about a time you learned a new language or framework quickly for a project.

HR & behaviouralKotlin FundamentalsEasy
Save to ▾
Show answer
Situation: my team switched a feature to Kotlin when I only knew Java. Task: deliver a profile screen in two weeks. Action: I spent the first evenings on the official Kotlin koans, converted small utility classes first, and asked a senior to review my early pull requests for idiomatic usage. Result: the screen shipped on time, and my later code needed far fewer review comments. I now learn by building something small immediately.
18

How would you lead an architecture decision when senior developers disagree?

Save to ▾
Show answer
I would write a short decision document stating the problem, two or three options with trade-offs, and constraints such as team skill and timeline, then build a small spike of the top options on a real screen. We review with measurable criteria like test effort and build time, decide, and record it as an architecture decision record. Once decided, everyone commits, and we revisit only if new facts appear.
19

How do you handle a situation where you are blocked by another team's API not being ready?

HR & behaviouralNetworking and APIsEasy
Save to ▾
Show answer
I agree on the API contract early, with sample JSON, and build against a fake or mock server so my UI and logic are ready. I keep the repository interface stable, so switching to the real API is a small change. I communicate status in standups and raise risks to my lead early if the dependency threatens the deadline, suggesting options like releasing behind a feature flag.
20

Where do you see yourself in five years as an Android developer?

Save to ▾
Show answer
Keep it genuine and tied to growth. For example: in five years I want to be a senior or lead Android engineer who owns the architecture of a large app, mentors juniors and works closely with product on decisions. I plan to deepen my skills in performance, Compose and Kotlin Multiplatform, and contribute to the team's engineering practices. I hope to grow that path in a company like this one.

Frequently asked questions

How do I use this mock interview?

Set a 50-minute timer, answer every question aloud (or ask a friend to read them), and open answers only after each round. Note every question where your answer missed the key idea.

How often should I take a mock?

Once a week while preparing and once two or three days before a real interview. The question order is fixed, so for fresh practice use the company and experience pages too.