← Back to list

Android Interview Questions I Was Actually Asked in 2026 — With Short Answers

Real Senior Android interview questions on Kotlin, Coroutines, Compose, architecture, debugging, testing, and pair programming.

Subin Babu · 2026-06-03 10:01 · 2 claps · 12.8 min read
#android-development #kotlin #mobile-app-development #technical-interview #software-engineering
Open on Medium ↗
Wiki topics: 💻 · Programming 📱 · Mobile Development 🏛️ · Architecture

What Android Interviewers Actually Asked Me in 2026 — With Short Answers

Preparing for Android interviews in 2026 feels different.

It is no longer enough to say, “I know Kotlin, MVVM, Clean Architecture, Coroutines, Flow, and Jetpack Compose.

Interviewers now want to know something deeper:

Can you explain your decisions clearly? Can you debug production issues? Can you reason about architecture trade-offs? Can you code simple logic under pressure? Can you connect Android knowledge to real product problems?

Over the last few months, I attended multiple Android interviews for Senior Android Developer roles across product companies, consultancies, media, banking, travel, and public-sector teams.

This post is a structured collection of real questions I faced, along with short answers that would work well in an interview.

1. “Explain Clean Architecture in Android.”

Clean Architecture separates the app into layers so business logic is independent from Android framework details. The usual structure is presentation, domain, and data. The presentation layer contains UI and ViewModel. The domain layer contains business models and use cases. The data layer contains repositories, APIs, databases, and data sources. The key rule is dependency direction: outer layers depend on inner layers, but the domain layer should not depend on Android, Retrofit, Room, or UI details. This improves testability, maintainability, and flexibility.

2. “Who depends on whom in Clean Architecture?”

The presentation layer depends on the domain layer, usually through use cases. The domain layer defines business rules and can define repository interfaces. The data layer implements those repository interfaces and depends on APIs, databases, and external services. The domain layer should not know whether data comes from Retrofit, Room, cache, Firebase, or any other source. Dependency Injection connects these implementations at runtime.

3. “Why do we need use cases? Why not call repository directly from ViewModel?”

For simple CRUD screens, calling a repository directly from ViewModel can be acceptable. But when business logic grows, use cases keep the ViewModel clean. A use case represents one action, such as login, fetch user profile, apply coupon, or submit order. It can combine multiple repositories, validate inputs, handle business rules, and make the logic easier to test. I use use cases when there is meaningful business logic, not just as a mandatory layer everywhere.

4. “What is MVVM?”

MVVM separates UI rendering from UI logic. The View observes state and sends user actions. The ViewModel handles UI logic, calls use cases or repositories, and exposes state using StateFlow or LiveData. The Model represents data or domain objects. In Android, ViewModel also helps survive configuration changes. The main benefit is testability and separation of concerns: UI stays simple, and logic can be tested without Android views.

5. “What are the disadvantages of MVVM?”

MVVM can become messy if the ViewModel grows too large. It may start holding too much UI logic, business logic, mapping logic, and navigation logic. State can also become difficult to debug if there are too many mutable flows or unclear events. To avoid this, I keep ViewModels focused on UI state and user actions, move business rules into use cases, use immutable UI state, and keep one clear source of truth.

6. “MVVM vs MVI — what is the difference?”

MVVM usually exposes UI state from the ViewModel and allows the UI to call ViewModel functions directly. MVI is more strict: the UI sends intents or events, the ViewModel/reducer processes them, and a single immutable state is produced. MVI is very useful for complex screens because state transitions are predictable and easier to debug. MVVM is simpler and works well for many screens. I choose based on screen complexity rather than using one pattern everywhere.

7. “How would you design a large-scale e-commerce Android app?”

I would divide the app by features such as home, search, product details, cart, checkout, orders, and profile. Each feature would follow presentation, domain, and data boundaries. The app would use repository interfaces, use cases for business actions, local caching where needed, and clear UI state handling. For scalability, I would focus on modularisation, API contract stability, offline/error handling, analytics, performance, secure payment flow, testing strategy, and release monitoring.

8. “How do you investigate slow app startup?”

First, I would measure instead of guessing. I’d check cold start and warm start timing, use Android Studio Profiler, Logcat, startup tracing, and possibly Macrobenchmark. Then I’d look for heavy work on the main thread, unnecessary SDK initialisation, blocking database calls, large dependency graphs, slow splash logic, or synchronous network calls. Fixes could include lazy initialisation, moving work off the main thread, reducing startup dependencies, and deferring non-critical SDKs.

9. “What causes ANR?”

ANR happens when the main thread is blocked for too long and the app cannot respond to user input or system events. Common causes include heavy database work, network calls, file I/O, bitmap processing, long loops, lock contention, or slow BroadcastReceiver work on the main thread. To prevent ANRs, I keep the main thread only for UI work, move blocking operations to Dispatchers.IO or background workers, monitor traces, and use tools like Profiler, Play Console vitals, and Crashlytics breadcrumbs.

10. “How do you handle production crashes?”

I start by checking Crashlytics or the crash reporting tool: stack trace, affected versions, device models, OS versions, user flow, and frequency. Then I try to reproduce it using the same app version and similar conditions. I check recent changes, logs, API responses, feature flags, and edge cases. After identifying the root cause, I add a safe fix, regression test if possible, and monitor the next release to confirm the crash rate has reduced.

11. “What is a memory leak in Android?”

A memory leak happens when an object is no longer needed but is still referenced, so the garbage collector cannot remove it. In Android, common leaks happen when Activity, Fragment, View, or Context references are held longer than their lifecycle. Examples include static references to Activity, callbacks not removed, observers not cleared, long-running coroutines tied to the wrong scope, or adapters holding old views. I detect leaks using LeakCanary, Android Studio Memory Profiler, heap dumps, and lifecycle-aware code reviews.

12. “How does garbage collection work?”

Garbage collection automatically frees memory by finding objects that are no longer reachable from active references. If an object is still reachable through a strong reference, it will not be collected even if the app no longer needs it. In Android, GC helps memory management, but it does not protect us from leaks caused by incorrect references. So we still need to manage lifecycle, unregister listeners, clear callbacks, avoid leaking Context, and use appropriate coroutine scopes.

13. “What tools do you use for memory and performance debugging?”

For memory issues, I use Android Studio Memory Profiler, heap dumps, allocation tracking, and LeakCanary. For CPU and performance, I use CPU Profiler, System Trace, Layout Inspector, and sometimes Macrobenchmark for startup or frame timing. For production signals, I use Crashlytics, Play Console vitals, logs, and custom analytics. The important part is to combine tool data with the user journey where the issue happens.

14. “What is a suspend function?”

A suspend function is a function that can pause execution without blocking the thread and later resume from the same point. Under the hood, Kotlin transforms suspend functions using continuations and a state-machine-like mechanism. In Android, suspend functions are useful for asynchronous work like network calls, database operations, or business logic. A suspend function does not automatically run on a background thread; we still need to use the right dispatcher when doing blocking work.

15. “launch vs async vs withContext?”

launch starts a coroutine and does not return a result. It returns a Job and is useful for fire-and-forget work inside a scope. async starts a coroutine that returns a Deferred result, and we call await() to get the value, usually for parallel tasks. withContext switches context inside the same coroutine and returns a result directly. I use withContext(Dispatchers.IO) for background work and async only when I genuinely need concurrency.

16. “coroutineScope vs supervisorScope?”

coroutineScope follows normal structured concurrency: if one child coroutine fails, the whole scope fails and cancels the other children. supervisorScope isolates child failures: one child can fail without cancelling its siblings. I use coroutineScope when all tasks depend on each other and should fail together. I use supervisorScope when tasks are independent, for example loading multiple optional sections of a screen where one failure should not break everything.

17. “How do you make suspend functions main-safe?”

A suspend function is main-safe when it can be safely called from the main thread without blocking UI. For example, if a repository performs disk or network work, it should switch internally to Dispatchers.IO using withContext. That way the caller, such as a ViewModel, does not need to know which dispatcher is required. This keeps threading responsibility close to the work being done and prevents accidental main-thread blocking.

18. “What is Flow?”

Flow is Kotlin’s cold asynchronous stream API. It can emit multiple values over time, unlike a suspend function which usually returns one result. In Android, Flow is useful for observing database changes, network states, UI state, search input, and real-time updates. Flow is cold by default, meaning it starts executing when collected. We can transform it using operators like map, filter, debounce, combine, catch, and collectLatest.

19. “StateFlow vs SharedFlow?”

StateFlow represents observable state. It always has a current value and is ideal for UI state such as loading, success, error, or screen data. SharedFlow is for events or broadcasts where we may not need a current value, such as navigation events, snackbars, or one-time messages. In modern Android, I usually expose StateFlow for screen state and use SharedFlow or Channel carefully for one-off events.

20. “How do you collect Flow safely in Android?”

I collect Flow in a lifecycle-aware way. In XML-based UI, I use repeatOnLifecycle from the Fragment or Activity. In Compose, I use collectAsStateWithLifecycle. This prevents collecting when the UI is stopped and avoids unnecessary work or leaks. The ViewModel exposes immutable StateFlow, and the UI observes it based on lifecycle state.

21. “What is Jetpack Compose?”

Jetpack Compose is Android’s modern declarative UI toolkit. Instead of manually updating views, we describe the UI as a function of state. When state changes, Compose recomposes the affected parts of the UI. It reduces boilerplate compared to XML, works well with Kotlin, and makes UI state handling more predictable when combined with ViewModel and StateFlow.

22. “What is recomposition?”

Recomposition is the process where Compose re-executes composable functions when the state they read changes. Compose tries to recompose only the affected parts instead of redrawing the whole screen. To keep recomposition efficient, we should keep state stable, avoid unnecessary object creation inside composables, use remember where appropriate, and keep side effects outside normal UI rendering logic.

23. “What are side effects in Compose?”

Side effects are operations that affect something outside the composable function, such as launching a coroutine, showing a snackbar, navigating, logging analytics, or calling an API. Since composables can recompose many times, we should not directly run side effects inside the composable body. Compose provides APIs like LaunchedEffect, DisposableEffect, SideEffect, rememberCoroutineScope, and produceState to handle these safely.

24. “What is dependency injection?”

Dependency Injection means providing a class its dependencies from outside instead of creating them inside the class. In Android, Hilt helps manage dependency graphs and object lifetimes. It improves testability because we can replace real dependencies with fakes or mocks. It also improves maintainability because object creation is centralised and classes depend on abstractions rather than concrete implementations.

25. “What is the difference between @Provides and @Binds in Hilt?”

@Provides is used when we need to manually create and return an object, for example Retrofit, Room database, or a class requiring builder logic. @Binds is used when we already have an implementation and want to bind it to an interface. @Binds is simpler and more efficient for interface-to-implementation mapping, while @Provides is better for construction logic.

26. “What is a Singleton?”

A Singleton means only one instance of a dependency is created and shared within a defined scope. In Hilt, @Singleton usually means the object lives as long as the application component. It is useful for dependencies like Retrofit, Room database, repositories, or shared managers. But I avoid making everything singleton because long-lived objects can hold memory unnecessarily or accidentally keep references to shorter-lived objects.

27. “How do you test ViewModel logic?”

I test ViewModel logic by replacing dependencies with fake use cases or repositories, using coroutine test tools like runTest, and verifying emitted UI state. For StateFlow, I check loading, success, and error states. I also inject test dispatchers instead of hardcoding Dispatchers. A good ViewModel test focuses on user actions and expected UI state, not Android framework details.

28. “Fake vs mock — what do you use in tests?”

A fake is a lightweight working implementation used for testing, while a mock verifies interactions and controlled responses. I prefer fakes when testing behaviour because they make tests easier to read and less fragile. I use mocks when I need to verify that a specific dependency was called with specific parameters. For repositories and use cases, fakes often give cleaner tests.

29. “How do you handle Room database migration?”

For Room migration, I define a migration from the old version to the new version using SQL changes such as creating tables, adding columns, or transforming data. I avoid destructive migration in production unless data loss is acceptable. I also test migrations with Room’s migration testing support to ensure existing user data remains valid after upgrade. Migration should be planned carefully because database mistakes can permanently affect user data.

30. “Where do you store JWT tokens securely?”

I avoid storing sensitive tokens in plain SharedPreferences. A safer approach is EncryptedSharedPreferences or encrypted storage backed by Android Keystore. Android Keystore can protect cryptographic keys so the app does not directly expose raw keys. For highly sensitive systems, I also consider token expiry, refresh token rotation, biometric protection if required, certificate pinning where appropriate, and clearing tokens on logout.

31. “How do you approach a pair-programming task?”

I first clarify the input, output, rules, and edge cases. Then I propose a simple model or data structure before coding. I prefer starting with a small working solution, then improving it. While coding, I explain my thinking, name variables clearly, and check examples manually. If I get stuck, I communicate what I know, what I’m unsure about, and how I plan to unblock myself.

32. “Write a function to aggregate monthly expenses.”

I would use a map where the key is the month and the value is the total amount. I would loop through each expense, extract the month from the date, and add the amount to the existing total. In Kotlin, this can be done with groupBy plus sumOf, or manually with a mutable map. In an interview, I would start with the simple readable version first, then discuss complexity: O(n) time and O(m) space, where m is the number of months.

33. “How would you model a card game like simplified Blackjack?”

I would start by modelling the domain clearly: Card, Suit, Rank, Deck, Player, and Hand. A deck has 52 cards: 13 ranks across 4 suits. Each player receives cards, and the hand calculates the score. Then I would implement game rules step by step: initial deal, blackjack check, player draw rule, dealer draw rule, bust condition, and winner decision. The key is to clarify rules before coding.

34. “How do you handle unfamiliar domains during pair programming?”

I clarify the domain before jumping into code. If the task is about a game, finance, warehouse robot, or any unfamiliar process, I ask for examples and confirm rules in simple language. Then I convert the domain into small models and behaviours. Interviewers usually care about problem-solving and communication, not just whether I already know the domain.

35. “Tell me about a difficult bug you fixed.”

A strong answer should explain the context, impact, investigation, fix, and learning. For example: in a production issue, I would first check crash reports, logs, affected versions, and reproduction steps. Then I would isolate whether the problem came from UI state, API response, database, concurrency, or lifecycle. After fixing it, I would add regression coverage and monitoring to prevent recurrence. The important part is showing a systematic debugging process.

36. “Tell me about a time you pushed back.”

I would push back when a requirement creates risk for performance, security, maintainability, or user experience. I would avoid saying “no” directly. Instead, I would explain the trade-off, show the impact, and suggest alternatives. For example, if a feature deadline risks skipping testing for a payment flow, I would propose a smaller safe release, feature flag, or phased rollout. Senior engineers should protect product quality while still helping delivery.

37. “How do you mentor junior developers?”

I mentor by giving context, not just answers. I review code with explanations, help juniors understand architecture decisions, suggest simpler solutions, and encourage them to write tests. I also give small ownership areas so they can grow gradually. Good mentoring means improving the team’s long-term quality, not becoming a bottleneck for every decision.

38. “What makes you senior?”

For me, seniority is not only years of experience. It is the ability to make good technical decisions, explain trade-offs, write maintainable code, debug production issues, support other developers, communicate clearly with product and backend teams, and take ownership beyond assigned tickets. A senior developer should reduce risk for the team and improve the quality of delivery.

39. “What are you improving now?”

I’m continuously improving my depth in Android performance, memory management, Coroutines and Flow, Jetpack Compose, testing, and system design. I’m also working on communicating my thought process more clearly during interviews and pair-programming sessions. Technical knowledge is important, but in senior interviews, how clearly we explain decisions is equally important.

What I Learned From These Interviews

The biggest lesson is this:

In 2026, Android interviews are not just checking whether you know APIs.

They are checking whether you can think like a senior engineer.

That means:

Can you explain architecture boundaries? Can you debug real production problems? Can you reason about memory, performance, and ANRs? Can you write simple Kotlin logic under pressure? Can you explain Coroutines and Flow clearly? Can you design a scalable app structure? Can you communicate when the problem domain is unfamiliar? Can you show ownership, not just implementation experience?

The questions are becoming more practical and more scenario-based.

A few years ago, many interviews asked, “What is MVVM?” Now they ask, “What are the disadvantages of MVVM in a large app?”

Earlier, they asked, “What is a coroutine?” Now they ask, “Why did this coroutine cause an ANR or cancellation issue?”

Earlier, they asked, “Have you used Clean Architecture?” Now they ask, “Who depends on whom, and why?”

That shift matters.

My Advice to Android Developers Preparing Now

Do not prepare only by memorising definitions.

Prepare short, clear, experience-based answers.

For every topic, practise this structure:

Definition → Why it matters → Real Android example → Trade-off

For example, do not just say:

“StateFlow is a hot flow.”

Say:

“StateFlow represents observable UI state. It always has a current value, which makes it suitable for screens like product details or checkout. I expose it from ViewModel as immutable state and collect it in Compose using lifecycle-aware APIs.”

That sounds more senior.

Final Thought

The best interview preparation is not collecting 500 questions.

It is learning to answer the 50 most important questions with clarity, confidence, and real project connection.

For Android interviews in 2026, focus on:

Kotlin fundamentals. Coroutines and Flow. Compose state and side effects. MVVM and Clean Architecture boundaries. Memory leaks and ANR debugging. Testing strategy. Simple pair-programming practice. Production issue investigation. Communication under pressure.

That is what interviewers are really testing now.


메타데이터
post_id
c0fb5cb67761
slug
android-interview-questions-i-was-actually-asked-in-2026-with-short-answers-c0fb5cb67761
url
https://medium.com/@subin.babu.samuel/android-interview-questions-i-was-actually-asked-in-2026-with-short-answers-c0fb5cb67761
canonical_url
https://medium.com/@subin.babu.samuel/android-interview-questions-i-was-actually-asked-in-2026-with-short-answers-c0fb5cb67761
author_url
https://medium.com/@subin.babu.samuel
status
ok
fetched_at
2026-06-09 15:37:30