Question 1
Difficulty: medium
Can you walk me through how you would structure a new Android app from scratch?
Sample answer
When I start a new Android app, I focus on keeping the architecture simple, scalable, and easy to test. I usually begin with a clean modular structure, separating presentation, domain, and data layers so responsibilities stay clear. For the UI layer, I prefer using ViewModel with Kotlin, Coroutines, and Flow, because it makes state handling predictable and lifecycle-aware. I also think carefully about navigation, dependency injection, and how data will move through the app before writing much code. On the data side, I like to define repositories that hide the source details, whether the data comes from Room, Retrofit, or a remote cache. I also set up logging, error handling, analytics, and a clear build configuration early, since these are easy to neglect and harder to add later. My goal is always to make the app maintainable for the next developer, not just functional for the first release.
Question 2
Difficulty: medium
How do you decide between using XML layouts and Jetpack Compose?
Sample answer
I decide based on the project’s current state, team experience, and long-term maintenance needs. If I’m joining an existing app that already uses XML heavily, I usually avoid forcing a full rewrite and instead introduce Compose gradually in contained areas. That keeps risk low and lets the team learn without disrupting delivery. If I’m starting a new product or a greenfield feature, I strongly consider Compose because it reduces boilerplate, makes UI state more explicit, and speeds up iteration once the team is comfortable with it. I also look at requirements like complex animations, accessibility, and testing. Compose is very strong there, but the team needs solid patterns for state hoisting and recomposition. I don’t treat it as a trendy default. I treat it as a tool choice, and I want the choice to improve delivery speed, readability, and maintainability in the actual context of the app.
Question 3
Difficulty: hard
Describe a time you had to fix a difficult performance issue in an Android app.
Sample answer
In one app, the main issue was a noticeable delay when opening a screen with a large feed. At first it looked like network latency, but after profiling I found the real problem was too much work happening on the main thread during rendering. We were mapping data, formatting strings, and preparing images all at once when the screen opened. I broke the work into smaller steps, moved data transformation off the UI thread, and used paging so we weren’t loading everything at once. I also cleaned up some unnecessary recompositions and reduced bitmap overhead by improving image loading and caching. After that, startup and scroll performance improved significantly. What I learned from that situation is that performance problems are often a combination of small issues rather than one big bug. I always profile first instead of guessing, because otherwise it’s easy to optimize the wrong thing and waste time.
Question 4
Difficulty: medium
How do you handle Android lifecycle-related bugs, especially around configuration changes?
Sample answer
Lifecycle bugs are some of the most common and frustrating issues in Android, so I try to design around them instead of patching them later. My first step is to understand which component owns the state and whether that state should survive rotation, process death, or just temporary UI changes. I keep screen state in the ViewModel whenever possible, and I use SavedStateHandle for values that need to survive process recreation. For one-time events like navigation or snackbars, I avoid storing them as permanent state and instead use a clear event mechanism. I also pay attention to what happens when the app goes to the background, because bugs often show up there rather than during normal use. If I’m debugging a lifecycle issue, I use logging and the Android Studio profiler to see exactly when objects are created, destroyed, or leaked. My approach is to make lifecycle behavior intentional, not accidental.
Question 5
Difficulty: medium
Tell me about a time you disagreed with a teammate about an implementation approach.
Sample answer
I once disagreed with a teammate about whether we should prioritize speed of delivery over introducing a more structured architecture for a new feature. They wanted a very direct implementation to meet the deadline, and I understood the urgency, but I was concerned the code would become hard to extend because the feature was expected to grow quickly. Instead of turning it into a debate about style, I asked what the next three releases of the feature would likely need. That helped us align on the fact that a small amount of structure now would save time later. We compromised by keeping the initial version lightweight but still separating UI, state, and data access clearly. That approach let us ship on time without creating a mess. I think the key in situations like that is to focus on the product impact, not personal preference. Good technical disagreements usually get resolved faster when both people are talking about tradeoffs instead of winning an argument.
Question 6
Difficulty: medium
How do you ensure your Android code is testable?
Sample answer
I make testability part of the design, not an afterthought. The biggest thing I do is keep business logic out of Activities and Fragments so it can be tested without relying on the Android framework. I prefer pushing logic into ViewModels, use cases, or repositories where dependencies can be replaced with fakes or mocks in tests. I also try to depend on interfaces when it makes sense, especially for data and system services, because that keeps unit tests simple and fast. For UI, I use a mix of unit tests and instrumented tests depending on the risk. For example, I’ll write unit tests for state transformations, validation, and edge cases, then use UI tests for critical flows like login or checkout. I’m also careful to keep tests readable and focused on behavior instead of implementation details. If a test is hard to write, I usually take that as a sign the production code may need a better separation of concerns.
Question 7
Difficulty: hard
How would you troubleshoot an app crash that only happens in production?
Sample answer
When a crash only appears in production, I start with the crash report and try to reproduce it using the exact context as much as possible: device type, OS version, app version, and user flow. I look at logs, stack traces, and analytics to identify patterns instead of assuming it’s a random issue. If needed, I’ll add more targeted logging or temporary diagnostics in a safe way so we can understand what’s happening without exposing user data. I also check whether the crash is tied to a particular data state, such as a null response, an empty list, or a race condition caused by asynchronous work. Once I identify the likely cause, I try to reproduce it locally and write a test so the fix is protected. I’ve learned that production-only crashes often come from edge cases the happy path never covers. The real challenge is being systematic and patient, because a fast guess is usually less useful than careful investigation.
Question 8
Difficulty: medium
What is your approach to working with APIs and handling network errors in Android?
Sample answer
My approach is to make network interactions predictable and resilient. I usually wrap API calls in a repository layer so the rest of the app doesn’t need to know about Retrofit details or response parsing. I convert raw responses into domain models and handle errors in a consistent way, including HTTP failures, timeouts, no connectivity, and malformed data. I also think carefully about loading states, retries, and user feedback, because a network call is never just about getting data; it’s also about what the user sees while waiting and what happens when it fails. For example, I’ll show cached data if possible, provide a clear retry action, and avoid blocking the UI while requests are in flight. I also use interceptors and centralized error mapping where appropriate so behavior stays consistent across the app. My goal is to make the app feel stable even when the network is not, because users judge reliability by how gracefully the app handles failure.
Question 9
Difficulty: easy
How do you stay current with Android platform changes and evolving best practices?
Sample answer
I try to stay current in a practical way rather than chasing every new release immediately. I read release notes for Android, Kotlin, and major Jetpack libraries because they often contain changes that affect real apps, especially around permissions, background work, and UI behavior. I also like to build small experiments with new APIs before using them in production, since that helps me understand their tradeoffs instead of just their syntax. In day-to-day work, I pay attention to code reviews, conference talks, and engineering blogs, but I’m selective about what I adopt. I look for patterns that improve clarity, testability, or user experience, not just newer tools. When I learn something useful, I try to share it with the team through a short doc or discussion so the knowledge spreads. I think strong Android developers keep learning, but they also know how to separate genuinely useful changes from trends that sound exciting but don’t solve a real problem.
Question 10
Difficulty: easy
Why do you want to work as an Android Developer on a product team rather than just building apps independently?
Sample answer
I enjoy building apps independently, but I get the most satisfaction from working on a product team where the work connects directly to real users and business goals. On a team, I can combine engineering quality with product thinking, which usually leads to better decisions than focusing only on technical elegance. I like collaborating with designers, backend engineers, QA, and product managers because each perspective improves the final app in a different way. That collaboration also makes me better at prioritizing, because not every problem deserves the same level of investment. In a product team, I can see how my code affects retention, conversion, performance, and user satisfaction, which makes the work feel more meaningful. I also enjoy the accountability of shared ownership. When something breaks or needs improvement, the team works together to solve it. For me, that environment is more motivating than building in isolation because it creates both technical depth and real-world impact.