Top 80 Android App Developer Interview Questions - 2025
Core Android (1–15)
1. What are the main Android app components?
Activities, Services, BroadcastReceivers, ContentProviders and (UI) Fragments. Each plays a role in UI, background work, inter-app data sharing, and lifecycle management.
2. Explain the Activity lifecycle.
Key callbacks: onCreate() → onStart() → onResume() (running) → onPause() → onStop() → onDestroy(). Handle short-term state with onSaveInstanceState(), persistent state in ViewModel/DB.
3. Activity vs Fragment — when to use which?
Use Activities as entry points (single responsibility). Use Fragments for modular, reusable UI within Activities — good for multi-pane/tablet layouts and navigation graphs.
4. What is a Context? Types and common pitfalls.
Context gives access to app resources, system services and lifecycle-aware operations. Types: Application, Activity, Service. Avoid leaking Activity Context (e.g., long-lived static references).
5. How does Android handle configuration changes (like rotation)?
By default Activities are destroyed and recreated. Use ViewModel to retain UI state, onSaveInstanceState() for small bundles, or handle configuration changes with manifest settings (not generally recommended).
6. Explain the differences between Serializable and Parcelable.
Serializable is Java-standard (slower). Parcelable is Android-optimized and faster for IPC. Prefer Parcelable for performance-critical bundles.
7. What is an Intent and IntentFilter?
Intent: message for components (explicit or implicit). IntentFilter: declares which intents a component can receive (actions, categories, data).
8. When to use a Service vs WorkManager vs Coroutine?
Use Service for long-running foreground tasks (media playback). Use WorkManager for deferrable, guaranteed background work (retries, constraints). Use Coroutines for structured concurrency in-process async operations.
9. What is StrictMode?
Developer tool to detect accidental disk/network access on main thread, leaked resources, etc. Useful to find performance and correctness issues during development.
10. Explain BroadcastReceiver and its types.
Component to listen for system or app intents. Two types: static (manifest-declared) and dynamic (registered at runtime). Static receivers have limitations on modern Android versions for implicit broadcasts.
11. App Manifest essentials and common entries.
Includes app package, activities, services, receivers, permissions, application-level attributes, and intent-filters. Use manifest for global declarations and permissions.
12. What are permissions? Runtime vs install-time.
Normal permissions are granted at install; dangerous permissions require runtime request (with rationale). Use ActivityResultContracts for simpler permission flows.
13. How to debug memory leaks in Android?
Use Android Profiler, LeakCanary (dev dependency), heap dumps and allocation tracking. Look for static references to Context, anonymous inner classes holding Activities, or long-lived callbacks.
14. What is DataStore and why prefer it over SharedPreferences?
DataStore (Preferences or Proto) is asynchronous, uses coroutines/Flow, is safe from main-thread IO, and offers schema via Proto. Prefer for modern, safer key-value storage.
15. Explain APK, AAB and Play Store delivery differences.
APK = distribution file. AAB = Android App Bundle (Google Play performs dynamic delivery and splits). AAB allows smaller installs via split APKs and on-demand modules.
Kotlin & Concurrency (16–30)
16. Why Kotlin for Android?
Kotlin is expressive, null-safe, concise, interoperable with Java, and has first-class support for coroutines and Android tooling. It's the recommended language for Android development.
17. Explain Kotlin Coroutines basics.
Coroutines provide lightweight threads and structured concurrency via launch, async, suspend functions and CoroutineScope. They simplify async code and cancellation.
18. What is a CoroutineScope? Where to use it in Android?
CoroutineScope defines the lifecycle of coroutines. Use viewModelScope in ViewModels, lifecycleScope in Activities/Fragments, and GlobalScope is discouraged.
19. Explain Dispatchers (Main, IO, Default).
Dispatchers.Main — main thread. Dispatchers.IO — blocking IO operations. Dispatchers.Default — CPU-intensive work. Choose based on work type.
20. How do you handle exceptions in coroutines?
Use try/catch in suspend functions or CoroutineExceptionHandler for top-level uncaught exceptions. Prefer structured error handling in repositories and ViewModels.
21. What are Flows and how are they different from LiveData?
Flow is Kotlin's reactive streams API, supports backpressure and operators. LiveData is lifecycle-aware and simpler for UI. Use Flow for more complex reactive pipelines; convert to LiveData when needed.
22. How to convert Flow to LiveData?
val live = myFlow.asLiveData()
23. Explain structured concurrency.
Child coroutines inherit the scope of their parent and are cancelled together, avoiding leaks. Use coroutineScope { ... } or supervisorScope { ... } to manage structured concurrency.
24. What is a suspend function?
A function marked suspend can suspend without blocking threads and resume later. It must be called from a coroutine or another suspend function.
25. Differences between launch and async.
launch starts a coroutine that returns Job (fire-and-forget). async returns Deferred and is used to retrieve a result via await().
26. How to cancel coroutines?
Call job.cancel() on the coroutine's Job or cancel the containing CoroutineScope. Use cooperative cancellation and check isActive in long-running loops.
27. Explain Channels vs Flow.
Channels are for communication between coroutines (hot, push-based). Flow is cold and pull-based. Use Channels for actor-like patterns; Flow for stream processing.
28. How to test coroutines?
Use runTest from kotlinx-coroutines-test, control dispatchers with TestDispatcher, and use dependency injection to swap dispatchers in tests.
29. Explain Kotlin sealed classes and use cases.
Sealed classes model restricted hierarchies (like Result states). Useful for UI state, events, and typed responses instead of enums.
30. What are inline, noinline and crossinline?
inline functions reduce lambda allocations by inlining code. noinline prevents a lambda parameter from being inlined. crossinline prohibits non-local returns in inlined lambdas.
Jetpack Compose (31–45)
31. What is Jetpack Compose?
Declarative UI toolkit for Android. Build UI with composable functions; UI reacts to state changes. Reduces boilerplate compared to XML.
32. What are Composables and how to create one?
@Composable
fun Greeting(name: String) {
Text(text = "Hello, $name")
}
33. How does Compose manage state?
Using state holders like remember, mutableStateOf, and ViewModel-backed StateFlow. Compose re-composes functions when observed state changes.
34. What causes recomposition and how to avoid unnecessary recompositions?
State changes trigger recomposition for affected composables. Avoid large recompositions by hoisting state, using remember, stable data classes, and splitting UI into smaller composables.
35. Explain remember vs rememberSaveable.
remember retains values across recompositions. rememberSaveable also survives process death via saved instance state (bundles).
36. How to perform side-effects in Compose?
Use Effect APIs: LaunchedEffect, SideEffect, DisposableEffect, and rememberCoroutineScope for coroutine-backed work.
37. How to integrate Compose with existing Views?
Use AndroidView to host Android Views and ComposeView to host Compose inside XML layouts.
38. How to build a list in Compose?
LazyColumn {
items(itemsList) { item ->
Text(item.title)
}
}
39. How to handle navigation in Compose?
Use androidx.navigation:navigation-compose for NavHost, NavController, and composable destinations. Use typed arguments and deep links when needed.
40. Explain modifiers in Compose.
Modifier chains describe layout, drawing, behavior (padding, click, size, background). They are immutable and composable.
41. How to handle forms and input validation?
Keep input state in ViewModel (StateFlow) or hoisted state. Validate on input change or submit and show error messages in UI. Debounce with Flow if needed.
42. Best practices for theming in Compose.
Use Material3 theme, color schemes, typography and shape tokens. Provide themes at top-level and use MaterialTheme for consistent styling.
43. How to animate in Compose?
Use animate*AsState, updateTransition, or low-level AnimationSpec. Compose animations are declarative and state-driven.
44. How to test Compose UIs?
Use compose-test library with createComposeRule(), semantics for nodes and matchers. Write assertions for existence, text, clicks and state changes.
45. Performance tips for Compose apps.
Minimize recomposition, use key in lists, avoid heavy work in composables, snapshot state immutability, and profile with LayoutInspector and system profilers.
Architecture & Dependency Injection (46–58)
46. What is MVVM and why use it?
MVVM separates UI (View), UI logic (ViewModel) and data (Model/Repository). ViewModel holds state and communicates with repositories. Increases testability and separation of concerns.
47. What is Clean Architecture?
Layered architecture dividing code into presentation, domain, and data. Dependencies point inward — domain layer is independent of frameworks.
48. What is Dependency Injection (DI)? Benefits?
DI provides dependencies instead of constructing them manually. Benefits: easier testing, modularity, and separation of concerns.
49. Why use Hilt? Basic example.
Hilt simplifies Dagger setup for Android by providing standard components and annotations. It integrates with ViewModels and Activities out of the box.
@HiltAndroidApp
class MyApp : Application()
@HiltViewModel
class UserVM @Inject constructor(private val repo: UserRepo): ViewModel()
50. How does scoping work in Hilt?
Hilt provides component scopes (SingletonComponent, ActivityComponent, FragmentComponent). Bindings have lifecycle matching their component.
51. How to write unit-testable Android code?
Follow SOLID principles, invert dependencies via interfaces, inject dependencies (Hilt), avoid Android SDK classes in domain layer, and write small pure functions.
52. What is Repository pattern?
Repository mediates between data sources (network, DB, cache) and ViewModel. It provides a clean API and centralizes data logic.
53. How to handle multiple module projects?
Split features into Gradle modules (app, core, feature-xyz). Keep domain/core utilities reusable. Use Gradle configuration and dependency constraints to manage versions.
54. What is Single Activity Architecture?
Single Activity hosts multiple fragments and uses Navigation Component for navigation. Simplifies shared ViewModel usage and deep-linking.
55. Explain Assisted Injection and when to use it.
Assisted injection supplies runtime parameters to injected classes (e.g., savedStateHandle). Use with complex object construction requiring runtime values.
56. How to manage app configuration and feature flags?
Use remote config (Firebase Remote Config), in-app toggles, and a centralized feature flag service. Keep default behavior safe and testable.
57. How to implement offline-first architecture?
Cache API responses in Room, serve cached data first, sync updates with WorkManager. Use network-bound resource pattern and conflict resolution strategies.
58. What is event handling best practice (singleLiveEvent vs Flow)?
Avoid SingleLiveEvent pitfalls; prefer SharedFlow or Channel for one-off events in ViewModels and convert appropriately for UI.
Networking & Databases (59–68)
59. How to use Retrofit with Coroutines?
interface Api {
@GET("users")
suspend fun getUsers(): List
}
Define suspend functions in service interfaces and call from repository inside appropriate dispatcher (IO).
60. What is OkHttp and why use it?
OkHttp is the underlying HTTP client used by Retrofit. It provides connection pooling, interceptors, HTTP/2 support, and caching.
61. How to handle API errors, retries and backoff?
Wrap network calls in try/catch, use Retrofit response codes, implement exponential backoff, and use WorkManager or retry operators in Flow for background retries.
62. What is Room and basic example?
@Entity
data class User(@PrimaryKey val id: Int, val name: String)
@Dao
interface UserDao {
@Query("SELECT * FROM User")
fun getAll(): Flow>
}
@Database(entities = [User::class], version = 1)
abstract class AppDb: RoomDatabase() { abstract fun userDao(): UserDao() }
63. How to migrate Room schema?
Provide Migration objects and pass into Room.databaseBuilder(...).addMigrations(...). Test migrations with database tooling.
64. When to use DataStore vs Room?
Use DataStore for small key-value preferences or proto-based typed config. Use Room for structured relational data with queries and transactions.
65. How to handle pagination?
Use Paging 3 library integrated with Room/Retrofit. Provide PagingSource, Pager and collect PagingData in UI via collectAsLazyPagingItems() in Compose or PagingDataAdapter in RecyclerView.
66. How to secure network requests (cert pinning, TLS)?
Use HTTPS, enable TLS 1.2+, add certificate pinning in OkHttp, validate server certificates, and avoid plain HTTP. Keep sensitive keys off the client.
67. How to cache network responses?
Configure OkHttp cache, set proper cache headers, and implement offline cache strategies with interceptors.
68. What are ContentProviders and when to use them?
ContentProvider exposes app data to other apps via a URI-based API. Use when sharing data between apps, e.g., media providers or contacts.
UI, Navigation & WorkManager (69–75)
69. Explain Navigation Component basics.
Navigation Component manages in-app navigation with NavHost, NavController, and navigation graphs. Supports safe args, deep links, and nested graphs.
70. How to pass data between fragments with Navigation Component?
Use SafeArgs plugin to create type-safe arguments: define arguments in nav graph and use generated directions classes to navigate.
71. What is WorkManager and when to use it?
WorkManager schedules deferrable, guaranteed background work respecting constraints (battery, network). Good for periodic syncs and one-off background tasks.
72. How to create a simple WorkManager task?
class SyncWorker(appContext: Context, params: WorkerParameters): CoroutineWorker(appContext, params) {
override suspend fun doWork(): Result {
// sync logic
return Result.success()
}
}
WorkManager.getInstance(context).enqueue(OneTimeWorkRequestBuilder().build())
73. How to implement deep links?
Declare deep links in nav graph or manifest. Use App Links (verified) for direct HTTP links and support intent filters for custom schemes.
74. Accessibility best practices for Android UI?
Provide content descriptions, support TalkBack, ensure proper focus order, large touch targets, sufficient contrast, and test with Accessibility Scanner.
75. How to handle multiple screen sizes and densities?
Use responsive layouts (ConstraintLayout/Compose), resource qualifiers, vector drawables, and provide multiple density assets or use adaptive images.
Testing, Performance & Security (76–80)
76. How to test Android apps (unit, instrumented, UI)?
Unit tests with JUnit and Mockito; instrumented tests on device/emulator with AndroidX Test; UI tests with Espresso or Compose testing. Use CI to run test suites.
77. Performance profiling tools and tips.
Use Android Profiler (CPU, Memory, Network), Systrace, Layout Inspector, and LeakCanary. Optimize bitmap usage, avoid main-thread IO, and reduce overdraw/Recomposition.
78. How to secure sensitive data on device?
Use EncryptedSharedPreferences / EncryptedFile, Android Keystore for keys, avoid storing plain text secrets, and use server-side tokens where possible.
79. How to handle app updates and migrations?
Design migration paths for data, use Room migrations, maintain backward compatibility for persisted data, and test upgrade paths. Use staged rollouts on Play Console.
80. What are common interview tips for Android roles?
Understand fundamentals (lifecycle, memory, threading), know Kotlin and Compose basics, show architecture and testing knowledge, bring real project examples, and explain trade-offs in design choices.
Create Beautiful Vertical & Horizontal Progress Indicators
