Here are Interview Questions for the Intermediate level 1-3 yrs of Experience level. Get ready for in-depth discussion during a face-to-face interview:
1. What is the Android Architecture?
Answer:
Android
architecture is a layered software stack that enables app developers to create
applications that run on the Android OS. It’s designed to abstract hardware
complexities and provide a flexible framework.
- Linux Kernel: The foundation providing core system
services like security, memory management, process management, and
hardware abstraction (e.g., drivers for camera, WiFi).
- Libraries & Android Runtime
(ART): Contains
native libraries written in C/C++ like SQLite for database
management, OpenGL ES for graphics, and WebKit for web rendering.
ART replaces the older Dalvik VM and improves performance by compiling
apps ahead of time.
- Application Framework: Provides Java/Kotlin APIs such
as ActivityManager (manages activities), WindowManager (handles UI windows),
Content Providers (manage data sharing), and NotificationManager.
- Applications: This is the topmost layer where
pre-installed apps like Phone, Contacts, and your own user apps run.
Example: When your app sends a notification, it
requests the NotificationManager (application framework), which interfaces with
system services via the Linux kernel to display the notification on screen.
2. What is the difference between Activity, Fragment, and
View?
Answer:
- Activity: Represents a full screen or
window in an app. It is the entry point for interacting with the user.
Activities have their own lifecycle and manage the UI components inside
them. They also act as containers for fragments.
- Fragment: Represents a reusable portion or
modular section of UI within an activity. It has its own lifecycle but
depends on the parent activity’s lifecycle. Fragments allow for more
dynamic and flexible UI designs, such as tabbed interfaces or multi-pane
layouts on tablets.
- View: The smallest building block of UI
components like buttons, text fields, images, etc. Views do not have their
own lifecycle; they are rendered inside activities or fragments.
Example: In a messaging app, the main activity
might host two fragments — one showing a list of conversations and another
displaying the chat. Each item in the list is a View.
3. Explain the Activity Lifecycle with a real-world use
case.
Answer:
An Activity
goes through several lifecycle states:
- onCreate() — Called when the activity is
first created. Initialize UI components here.
- onStart() — Called when the activity is
becoming visible.
- onResume() — Called when the activity starts
interacting with the user.
- onPause() — Called when the system is about
to put the activity into the background.
- onStop() — Called when the activity is no
longer visible.
- onRestart() — Called after the activity has
been stopped, just before it starts again.
- onDestroy() — Called before the activity is
destroyed.
Use Case: In an expense tracking app, when a
user switches away (onPause), you might save draft data or pause sensor
updates. When the user returns (onResume), you refresh the UI and data. onSaveInstanceState() can be used to save UI state during rotation.
4. What is ViewModel and why is it useful?
Answer:
ViewModel is an
architecture component designed to store and manage UI-related data in a
lifecycle-conscious way. It survives configuration changes such as device
rotations, which destroy and recreate activities.
Why use
ViewModel?
- It separates UI data from UI
controllers (Activities/Fragments), making code cleaner.
- Avoids expensive re-fetching of
data on rotation.
- Integrates well with LiveData for
reactive UI updates.
Example: In a weather app, you fetch the
current weather in ViewModel. When the device rotates, the ViewModel persists,
so your app doesn’t make redundant network calls.
5. What is LiveData and how does it work with ViewModel?
Answer:
LiveData is a
lifecycle-aware observable data holder. It respects the lifecycle state of UI
components and only updates observers when they are active.
- Prevents memory leaks by
automatically cleaning up observers.
- Ensures UI updates happen only
when the Activity/Fragment is in a valid state.
- Simplifies asynchronous UI
updates.
Example: A stock price LiveData in ViewModel
updates the UI automatically when the data changes. Observers in the Activity
subscribe using observe() and get notified without manual
lifecycle handling.
6. What is the difference between LiveData and StateFlow?
Answer:
Both are
observable data holders but differ in origin and features:
- LiveData: Lifecycle-aware, built for
Android, updates observers only when UI is active, easy to integrate with
ViewModel and DataBinding.
- StateFlow: Part of Kotlin Coroutines, always
holds a current value, requires manual lifecycle management with repeatOnLifecycle or similar, better for complex
data streams.
Use LiveData if
you want simple lifecycle awareness; use StateFlow for advanced asynchronous
flows with coroutines.
7. How do you handle configuration changes in Android?
Answer:
Configuration
changes (e.g., rotation, locale changes) restart the activity by default, which
can cause data loss.
- Use ViewModel to retain
data across config changes.
- Use onSaveInstanceState() to save small UI state like scroll position.
- Avoid android:configChanges in manifest unless necessary (it
prevents recreation but can cause issues).
- For complex cases, use retained
fragments or saved state modules.
8. What is the difference between implicit and explicit
intents?
Answer:
- Explicit Intent: Specifies the exact component to
start by name (class). Used for internal app communication.
- Implicit Intent: Specifies an action to perform,
letting Android find suitable apps. Used for system-wide actions like
sharing or opening URLs.
Example:
Explicit — Intent(this,
DetailActivity::class.java)
Implicit — Intent(Intent.ACTION_VIEW,
Uri.parse("https://google.com"))
9. How does data persistence work in Android?
Answer:
Android
provides various ways to persist data:
- SharedPreferences: Store key-value pairs for small
data like user settings.
- SQLite/Room: Structured relational database
for complex, large datasets.
- Files: Store binary/text files like
images or logs.
- DataStore: Modern replacement for
SharedPreferences, based on Kotlin Coroutines and Flow, providing
asynchronous and consistent data storage.
Choose the
method based on data size, structure, and access pattern.
10. What is Room Database and how is it different from
SQLite?
Answer:
Room is a
wrapper over SQLite designed to simplify database access and improve
maintainability.
- Provides compile-time checks for
SQL queries.
- Reduces boilerplate code by
generating much of the SQLite interaction.
- Supports observable queries with
LiveData or Flow.
- Components:
- @Entity: Defines database tables.
- @Dao: Data Access Object, defines SQL
queries.
- @Database: Connects entities and DAOs.
Room helps
avoid common SQLite pitfalls like runtime errors and tedious cursor management.
11. What is Coroutine and why is it used in Android?
Answer:
Coroutines are
Kotlin’s way of handling asynchronous programming and concurrency with a simple
and efficient API. Unlike traditional threads, coroutines are lightweight and
can be suspended and resumed without blocking the main thread.
- Why use Coroutines?
- Avoids blocking the main (UI)
thread during long operations such as network calls, file I/O, or
database access.
- More efficient and less
resource-intensive compared to Java threads.
- Structured concurrency:
coroutines can be scoped and managed, reducing memory leaks and uncontrolled
execution.
- Supports cancellation and timeout
out-of-the-box.
Example:
kotlin
CopyEdit
viewModelScope.launch {
val data =
repository.getDataFromNetwork()
_uiState.value
= data
}
Here, viewModelScope ensures the coroutine is canceled if the ViewModel is
destroyed, preventing memory leaks.
12. What is the difference between suspend functions and
regular functions?
Answer:
- Regular functions execute synchronously and run to
completion once called.
- Suspend functions are marked with the suspend modifier and can suspend
execution without blocking the current thread.
- Suspend functions can only be
called from other suspend functions or coroutines.
- They are designed to run
long-running operations asynchronously but allow easy, sequential style
code.
Example:
kotlin
CopyEdit
suspend fun fetchUser(): User {
return
api.getUserData()
}
This can be
called inside a coroutine, and it suspends while waiting for the network
response.
13. What is MVVM architecture in Android?
Answer:
MVVM
(Model-View-ViewModel) is a design pattern that separates concerns and improves
maintainability:
- Model: Data layer that represents your
business logic and data sources (local DB, network, etc.).
- ViewModel: Acts as a bridge between the
Model and View, holding UI data and handling business logic for the UI. It
survives configuration changes.
- View: The UI layer (Activity/Fragment)
that observes the ViewModel and updates the UI reactively.
Benefits:
- Cleaner, testable, and
maintainable code.
- UI logic separated from business/data
logic.
- Works well with LiveData or
StateFlow for reactive programming.
14. How do you handle API errors in Android?
Answer:
Handling API
errors gracefully is critical for good UX:
- Use try-catch blocks around API
calls or use Retrofit’s error handling.
- Implement a sealed class or
wrapper for different states such as:
- Success (with data),
- Loading (for progress indicators),
- Error (with exception details).
- Show user-friendly messages based
on error type (network error, timeout, server error).
- Implement retry logic or fallback
data.
Example sealed
class:
kotlin
CopyEdit
sealed class Result<out T> {
data class
Success<T>(val data: T): Result<T>()
data class
Error(val exception: Throwable): Result<Nothing>()
object Loading:
Result<Nothing>()
}
15. What is Hilt and how does it help with dependency
injection?
Answer:
Hilt is a
dependency injection (DI) library for Android built on top of Dagger, designed
to simplify DI setup and usage.
- Automates the generation of DI
code.
- Provides predefined components
tied to Android lifecycle (Application, Activity, Fragment).
- Integrates with Jetpack components
like ViewModel, WorkManager, Navigation.
- Reduces boilerplate compared to
manual Dagger setup.
- Improves app modularity, testing,
and code readability.
Example:
- Annotate the Application class
with @HiltAndroidApp.
- Annotate Activities/Fragments with
@AndroidEntryPoint.
- Inject dependencies using @Inject in constructors.
16. What are sealed classes in Kotlin and how are they
useful in Android?
Answer:
Sealed classes
are a special kind of class that restricts the hierarchy to a fixed set of
subclasses, all known at compile time.
- Useful for representing restricted
types with a fixed number of possible states.
- Ideal for modeling state machines,
result wrappers (success, error, loading).
- The compiler knows all subclasses,
enabling exhaustive when statements without needing an else branch.
Example:
kotlin
CopyEdit
sealed class NetworkResult<out T> {
object Loading:
NetworkResult<Nothing>()
data class
Success<T>(val data: T): NetworkResult<T>()
data class
Error(val exception: Throwable): NetworkResult<Nothing>()
}
17. Explain how WorkManager works and when to use it.
Answer:
WorkManager is
a Jetpack library for managing deferrable, guaranteed background work, even if
the app exits or the device restarts.
- Supports constraints like network
availability or charging status.
- Work requests can be chained or
combined.
- Ensures tasks are executed
reliably using JobScheduler, AlarmManager, or Firebase JobDispatcher under
the hood depending on API level.
- Works well for periodic or
one-time background tasks such as syncing data, uploading logs, or
processing images.
Example:
kotlin
CopyEdit
val workRequest =
OneTimeWorkRequestBuilder<MyWorker>().build()
WorkManager.getInstance(context).enqueue(workRequest)
18. How do you optimize Android app performance?
Answer:
Common
optimization strategies:
- Avoid heavy operations on the main
thread.
- Use efficient data structures and
algorithms.
- Optimize layouts by reducing
nested views or using ConstraintLayout.
- Use RecyclerView for long lists
with ViewHolder pattern.
- Use caching and pagination for
network data.
- Avoid memory leaks by managing
references properly.
- Use profiling tools (Android Profiler,
LeakCanary) to monitor CPU, memory, and network.
- Optimize images by using proper
formats and sizes.
- Use ProGuard or R8 for code
shrinking and obfuscation.
19. What is the difference between Parcelable and
Serializable in Android?
Answer:
Both are interfaces
to serialize objects for passing between activities or saving state, but:
- Parcelable: Android-specific, faster, more
efficient as it requires manual implementation of serialization logic.
Recommended for Android.
- Serializable: Java standard, slower due to
reflection and generates more garbage, easier to implement (marker
interface).
Use Parcelable
for performance-critical Android apps, especially when passing large data via
Intent extras.
20. How do you secure data in Android apps?
Answer:
Important
practices include:
- Use Android Keystore System
to store cryptographic keys securely.
- Use EncryptedSharedPreferences
and EncryptedFile to store sensitive data.
- Avoid storing sensitive data in
plaintext or on external storage.
- Use HTTPS with SSL/TLS for network
communication.
- Minimize permissions to only what
your app requires.
- Obfuscate code using ProGuard/R8.
- Use user authentication and
biometrics APIs.
- Validate all inputs to prevent
injection attacks.
21. What is Android Jetpack and what are its components?
Answer:
Android Jetpack
is a set of libraries, tools, and architectural guidance provided by Google to
help developers write high-quality, maintainable apps easily.
Key Components:
- Architecture Components: ViewModel, LiveData, Room, WorkManager
— help manage lifecycle, data persistence, background work.
- UI Components: Navigation (handles app
navigation and deep linking), Paging (loads data gradually), Animation.
- Behavior Components: Notifications, Permissions,
Sharing.
- Foundation Components: AppCompat (backward
compatibility), Multidex, Test.
Jetpack
simplifies common development tasks and encourages best practices with reactive
and lifecycle-aware components.
22. How does Room handle database migrations?
Answer:
Room supports
schema migrations when you change your database schema (e.g., add/remove
columns or tables).
- You provide a Migration
object defining how to convert the old schema to the new one using SQL
statements.
- Room runs this migration when the
database version is incremented.
- If you don’t provide migrations,
Room throws a IllegalStateException on version mismatch.
- You can fallback to destructive
migration (fallbackToDestructiveMigration()) which deletes the database but
is not recommended for production.
Example:
kotlin
CopyEdit
val MIGRATION_1_2 = object : Migration(1, 2) {
override fun
migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE users ADD COLUMN last_update
INTEGER")
}
}
23. What are Broadcast Receivers and how are they used?
Answer:
Broadcast
Receivers listen for system-wide or app-wide broadcast messages (Intents) and
react accordingly.
- They handle asynchronous events
like battery low, connectivity changes, or custom app events.
- Can be registered statically in AndroidManifest.xml or dynamically in code.
- Use onReceive() callback to handle the event.
- Limited execution time (about 10
seconds) in onReceive().
Example: Listening for network connectivity
changes to update UI or retry operations.
24. Explain the difference between Service,
IntentService, and JobIntentService.
Answer:
- Service: Runs in the background to perform
long-running operations without user interaction. Runs on the main thread,
so developers must manage threading manually.
- IntentService (deprecated): A subclass of Service that
handles asynchronous requests on a worker thread and stops itself when
done. Good for short tasks.
- JobIntentService: Supports background execution
compatible with newer Android versions with restrictions on background
services. It queues work and executes it on a background thread respecting
OS constraints.
25. What is the difference between apply() and commit() in
SharedPreferences?
Answer:
- commit(): Synchronously writes changes to
disk and returns a boolean indicating success. Blocks the calling thread.
- apply(): Asynchronously writes changes and
returns immediately. Changes are persisted in the background. No success
status.
Best Practice: Use apply() for non-critical settings to avoid blocking the UI thread.
No comments:
Post a Comment