Latest Android Interview questions and answers
- Elaborate your approach in integrating a third party API into your project?
My approach is to treat any 3rd-party API as a 'black box' that we don't trust. I wrap it behind an interface to decouple it from our business logic, use Mappers to control the data flow, and implement strict error-handling policies like exponential backoff to ensure the app remains stable even if the service goes down.
1. Evaluation and Research - Documentation & Support, License & Security, Performance Impact
2. Architectural Integration (The "Wrapper" Pattern) - Abstraction Layer
3. Implementation Strategy - Dependency Injection, Concurrency, Data Transformation
4. Robustness and Resilience - Error Handling, Retry Mechanisms, Caching & Offline Support
5. Monitoring and Observability - Logging & Analytics, Health Checks - What is a singleton pattern and how singleton declared in Kotlin?
The Singleton Pattern is a creational design pattern that ensures a class has only one instance throughout the entire lifecycle of an application and provides a global point of access to that instance. In Android, this is commonly used for shared resources like a database instance (Room), a network client (Retrofit), or a preferences manager.
A. The object Keyword (The Standard Way)
B. Companion Object with by lazy
C. Double-Checked Locking (For Parameters) - What are the layouts available in jetpack compose
1. Foundational Layouts - Column, Row, Box
2. Lazy Layouts (List & Grid) - LazyColumn, LazyRow, LazyVerticalGrid / LazyHorizontalGrid, LazyVerticalStaggeredGrid
3. High-Level & Material Layouts - Scaffold, Surface, Card
4. Constraint & Specialized Layouts - ConstraintLayout, BoxWithConstraints, FlowRow / FlowColumn - What are state hoisting in jetpack compose
In Jetpack Compose, State Hoisting is a pattern of moving state to a composable's caller to make the composable stateless.
Without Hoisting (Stateful)
In this version, the SearchField is hard to test or reuse because it controls its own state. If you wanted to clear the search from a "Reset" button elsewhere, you couldn't.
@Composable
fun SearchField() {
var text by remember { mutableStateOf("") } // Internal state
TextField(value = text, onValueChange = { text = it })
}
With Hoisting (Stateless)
Now, the SearchField is purely a UI component. The parent controls what it shows and what happens when the user types.
@Composable
fun SearchScreen()
{
var query by remember { mutableStateOf("") } // State lives here
Column {
SearchField( value = query, onValueChange = { query = it } )
Text("You are searching for: $query")
}
}
@Composable
fun SearchField(value: String, onValueChange: (String) -> Unit)
{
TextField(value = value, onValueChange = onValueChange)
}
Why is State Hoisting Important?
Single Source of Truth
Testability
Decoupling
Reusability
- Describe the approach you follow to integrate a web service into your application
My approach is to treat the web service as a plugin. I wrap it in a Repository, use Interceptors for security and logging, and ensure that the UI only ever interacts with clean Domain models rather than raw JSON objects. This makes the app resilient to API changes and highly testable.
I follow, structured from architecture down to execution
1. Architectural Strategy (Layered Approach) - Data Source, Repository, Domain (Use Cases)
2. Technical Implementation Details - Serialization, Interceptors - Authentication,Logging,Connectivity, Timeout Policies
3. Resilience and Error Handling - Result Wrapper, Exponential Backoff, Coroutines & Threading
4. Security Measures - SSL Pinning, Data Masking, Encrypted Storage
5. Testing & Observability - MockWebServer, Health Monitoring - How do you handle the error exceptions
I follow a 'fail-safe' approach. I wrap all boundary operations (API/Database) in a Sealed Result class, map technical exceptions to user-friendly domain errors, and use Coroutine Exception Handlers to ensure that no background failure ever leads to a silent crash. Finally, I use centralized logging to track these errors in production.
1. Using Sealed Classes for Functional Error Handling - Instead of letting exceptions propagate up to the UI and risk a crash, I wrap network and disk operations in a Result sealed class.
2. Mapping Exceptions to "App Exceptions" - use a Mapper to convert technical errors into domain-specific errors.
3. Global Exception Handling Strategies -
A. The Retrofit / OkHttp Level - I use an Interceptors to catch specific HTTP codes globally.
B. The ViewModel Level (Coroutine Exception Handler) - When using Coroutines, I use a CoroutineExceptionHandler to catch "unhandled" exceptions in the background scope
4. User-Facing Error Communication - Actionable Errors, Non-Blocking Errors, Catastrophic Errors
5. Observability and Reporting - If an error happens in the field, the team needs to know by Crashlytics and Breadcrumbs - I need to run two API calls in parallel, and if anyone API call fails i need to cancel the other, and show the error dialog that API call is not success.
-To handle two parallel API calls where the failure of one immediately cancels the other and triggers an error dialog, you should use Kotlin Coroutines with coroutineScope and async-await.
-In Kotlin, a standard coroutineScope exhibits fail-fast behavior. If any child coroutine within the scope fails with an exception, the entire scope is immediately canceled—automatically terminating all other sibling coroutines—and the exception is propagated up to be caught in a try-catch block.fun fetchParallelData(){viewModelScope.launch {
try {
// coroutineScope enforces structured concurrency and fail-fast mechanics
coroutineScope {
// Start both API calls concurrently
val apiCallOne = async { repository.getFirstData() }
val apiCallTwo = async { repository.getSecondData() }
// Await results. If either throws an exception,
// the other is instantly canceled by the parent scope.
val resultOne = apiCallOne.await()
val resultTwo = apiCallTwo.await()
// Handle your combined successful results here
processResults(resultOne, resultTwo)
}
} catch (e: Exception) {
// Handle the propagated failure and notify the UI layer
_errorEvent.emit(e.localizedMessage ?: "API call is not success.")
}
}
}
private fun processResults(res1: Any, res2: Any) { /* ... */ } - Idelling resource in expresso
By default, Espresso is "smart"—it waits for the UI thread to be idle (no pending messages in the Looper) and for AsyncTask to finish before moving to the next test step. However, Espresso cannot see into your custom background threads, Kotlin Coroutines, or third-party libraries like Retrofit or RxJava.
An Idling Resource is a marker you use to tell Espresso: "The app is still doing something important in the background. Please wait for this specific task to finish before you continue with the test assertions." - Content management system like AEM ?
- Write a program in kotlin that will remove the duplicates from the list and sort them in ascending order
- Difference between set and a mutable set
- What is build type, build Variants and product flavour
- How does AI help in development
- Describe one positive and one negative about gen-Z employee we work with
Comments
Post a Comment