├── Kotlin Sheet 2024.gif ├── Jetpack Compose 2024.gif ├── Top 10 Kotlin Coroutines Interview Questions - Senior Android Engineer Guide.pdf ├── CONTRIBUTING.md ├── Detail Questions and Answers.md └── README.md /Kotlin Sheet 2024.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anandwana001/android-interview/HEAD/Kotlin Sheet 2024.gif -------------------------------------------------------------------------------- /Jetpack Compose 2024.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anandwana001/android-interview/HEAD/Jetpack Compose 2024.gif -------------------------------------------------------------------------------- /Top 10 Kotlin Coroutines Interview Questions - Senior Android Engineer Guide.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anandwana001/android-interview/HEAD/Top 10 Kotlin Coroutines Interview Questions - Senior Android Engineer Guide.pdf -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # 🤝 Contributing to Android Interview Questions 2 | 3 | First off, thank you for taking the time to contribute! 🎉 4 | This project is open-source and community-driven — every question and answer makes a difference. 5 | 6 | --- 7 | 8 | ## 📌 How to Contribute 9 | 10 | 1. **Fork the repository** 11 | Click the "Fork" button at the top right of this repo to create your own copy. 12 | 13 | 2. **Clone your fork locally** 14 | 15 | ```bash 16 | git clone https://github.com/anandwana001/android-interview-questions.git 17 | cd android-interview-questions 18 | ``` 19 | 20 | 3. **Create a new branch** 21 | 22 | ```bash 23 | git checkout -b add-my-question 24 | ``` 25 | 26 | 4. **Add your question (and answer, if you want)** 27 | 28 | * Go to the `readme.md` file. 29 | * Add your question. 30 | 31 | Example format: 32 | 33 | ```markdown 34 | ### Question: Explain the difference between `LiveData` and `StateFlow` in Android? 35 | 36 | **Answer (Optional):** 37 | - `LiveData` is lifecycle-aware and commonly used in MVVM. 38 | - `StateFlow` is part of Kotlin Coroutines, hot stream, and provides more predictable state handling. 39 | ``` 40 | 41 | 5. **Commit your changes** 42 | 43 | ```bash 44 | git add . 45 | git commit -m "Added question about LiveData vs StateFlow" 46 | ``` 47 | 48 | 6. **Push to your fork** 49 | 50 | ```bash 51 | git push origin add-my-question 52 | ``` 53 | 54 | 7. **Open a Pull Request (PR)** 55 | 56 | * Go to this repo on GitHub. 57 | * Click **“Compare & Pull Request”**. 58 | * Add a short description of your contribution. 59 | 60 | --- 61 | 62 | ## ✅ Contribution Guidelines 63 | 64 | * Keep questions **clear and concise**. 65 | * Adding an **answer is optional** but highly appreciated. 66 | * Multiple PRs are welcome! 67 | 68 | --- 69 | 70 | ## 🌟 Recognition 71 | 72 | * Your GitHub profile will be listed in the **Contributors** section. 73 | * You’ll be part of building the **largest open-source Android interview prep repo** 🚀 74 | 75 | 76 | -------------------------------------------------------------------------------- /Detail Questions and Answers.md: -------------------------------------------------------------------------------- 1 | # 🧠 Detailed Questions and Answers 2 | 3 | ## Book 1:1 Session here -> [Click Here](https://rzp.io/l/HVG4Zx4qFO) 4 | 5 | ### 🚦 Suspend Functions and How Suspension Works 6 | 7 | #### What are Suspend Functions? 8 | 9 | A **suspend function** is a function that can be paused and resumed without blocking the thread it's running on. 10 | 11 | > Think of it like a video game where you can pause the game, do something else, and then resume exactly where you left off. 12 | 13 | ```kotlin 14 | suspend fun fetchUserData(userId: Int): User { 15 | // This function can be suspended 16 | return apiService.getUser(userId) // Network call that might suspend 17 | } 18 | ``` 19 | 20 | #### 🍽️ The Restaurant Waiter Metaphor 21 | 22 | * **Blocking approach (regular functions):** 23 | 24 | * Take order at table 1 25 | * Wait at the table until food is ready (thread blocked) 26 | * Can’t serve others = inefficient 27 | 28 | * **Suspend function approach:** 29 | 30 | * Take order and give it to the kitchen (suspend) 31 | * Serve other tables while waiting (thread free) 32 | * Return to table 1 when food is ready (resume) 33 | 34 | 35 | 36 | #### 🧪 How Suspension Works Internally 37 | 38 | * **Continuation-Passing Style (CPS):** Compiler adds a continuation parameter 39 | * **State Machine:** Transforms suspend functions into state machines 40 | * **Thread Release:** Suspends release thread resources 41 | * **Resume:** Coroutine resumes where it left off 42 | 43 | ```kotlin 44 | suspend fun example() { 45 | println("Before") 46 | delay(1000) // Suspension point 47 | println("After") 48 | } 49 | ``` 50 | 51 | Transformed internally to: 52 | 53 | ```kotlin 54 | fun example(continuation: Continuation): Any? { 55 | val sm = continuation as? ExampleStateMachine ?: ExampleStateMachine(continuation) 56 | 57 | when (sm.label) { 58 | 0 -> { 59 | println("Before") 60 | sm.label = 1 61 | return delay(1000, sm) 62 | } 63 | 1 -> { 64 | println("After") 65 | return Unit 66 | } 67 | } 68 | } 69 | ``` 70 | 71 | --- 72 | 73 | #### 💾 Real-World Example: File Download 74 | 75 | ```kotlin 76 | class FileDownloader { 77 | suspend fun downloadFile(url: String): ByteArray { 78 | println("Starting download from $url") 79 | val response = httpClient.get(url) // Suspension point 80 | val data = response.readBytes() // Another suspension point 81 | println("Download complete!") 82 | return data 83 | } 84 | } 85 | 86 | suspend fun downloadMultipleFiles() { 87 | val downloader = FileDownloader() 88 | 89 | val file1 = async { downloader.downloadFile("https://example.com/file1.zip") } 90 | val file2 = async { downloader.downloadFile("https://example.com/file2.zip") } 91 | 92 | val results = awaitAll(file1, file2) 93 | } 94 | ``` 95 | 96 | --- 97 | 98 | ### 🧱 `runBlocking` vs `coroutineScope` 99 | 100 | #### 🛤️ The Bridge Metaphor 101 | 102 | * `runBlocking`: A drawbridge — stops all traffic (blocks thread) 103 | * `coroutineScope`: A pedestrian overpass — lets traffic flow underneath (non-blocking) 104 | 105 | 106 | 107 | #### ⛔ runBlocking - The Blocking Bridge 108 | 109 | ```kotlin 110 | fun main() { 111 | println("Before runBlocking") 112 | 113 | runBlocking { 114 | println("Inside coroutine") 115 | delay(2000) 116 | println("Coroutine done") 117 | } 118 | 119 | println("After runBlocking") 120 | } 121 | ``` 122 | 123 | ✅ Characteristics: 124 | 125 | * Blocks the calling thread 126 | * Used in `main()` and tests 127 | * Bridges regular code with coroutines 128 | 129 | 130 | 131 | #### ✅ coroutineScope - The Non-Blocking Scope 132 | 133 | ```kotlin 134 | suspend fun processUserData(userId: Int) { 135 | println("Starting processing for user $userId") 136 | 137 | coroutineScope { 138 | val profile = async { fetchUserProfile(userId) } 139 | val posts = async { fetchUserPosts(userId) } 140 | val friends = async { fetchUserFriends(userId) } 141 | 142 | val userProfile = profile.await() 143 | val userPosts = posts.await() 144 | val userFriends = friends.await() 145 | 146 | println("All data fetched for user $userId") 147 | } 148 | 149 | println("Processing complete") 150 | } 151 | ``` 152 | 153 | ✅ Characteristics: 154 | 155 | * Does **not** block the thread 156 | * Can only be called from `suspend` functions 157 | * Provides structured concurrency 158 | 159 | 160 | 161 | #### 🛒 Real-World Example: E-commerce Order Processing 162 | 163 | ```kotlin 164 | class OrderProcessor { 165 | fun processOrderBlocking(orderId: String) { 166 | runBlocking { 167 | processOrder(orderId) 168 | } 169 | } 170 | 171 | suspend fun processOrder(orderId: String) { 172 | coroutineScope { 173 | val inventory = async { checkInventory(orderId) } 174 | val payment = async { processPayment(orderId) } 175 | val shipping = async { calculateShipping(orderId) } 176 | 177 | val inventoryResult = inventory.await() 178 | val paymentResult = payment.await() 179 | val shippingResult = shipping.await() 180 | 181 | if (inventoryResult && paymentResult) { 182 | async { updateInventory(orderId) } 183 | async { sendConfirmationEmail(orderId) } 184 | async { scheduleShipping(orderId, shippingResult) } 185 | } 186 | } 187 | 188 | println("Order $orderId processing complete") 189 | } 190 | 191 | private suspend fun checkInventory(orderId: String) = delay(500).let { true } 192 | private suspend fun processPayment(orderId: String) = delay(1000).let { true } 193 | private suspend fun calculateShipping(orderId: String) = delay(300).let { ShippingInfo("2-day", 9.99) } 194 | } 195 | 196 | fun main() { 197 | val processor = OrderProcessor() 198 | processor.processOrderBlocking("ORD-12345") 199 | } 200 | 201 | suspend fun handleApiRequest(orderId: String) { 202 | val processor = OrderProcessor() 203 | processor.processOrder(orderId) 204 | } 205 | ``` 206 | 207 | 208 | ### 🧾 Key Differences Summary: `runBlocking` vs `coroutineScope` 209 | 210 | | **Aspect** | **`runBlocking`** | **`coroutineScope`** | 211 | | ---------------------- | -------------------------------------------- | -------------------------------------------------------- | 212 | | **Thread Blocking** | Blocks the calling thread | Does **not** block the calling thread | 213 | | **Usage Context** | Regular functions, `main()`, tests | Only within `suspend` functions | 214 | | **Purpose** | Bridge from blocking code to coroutine world | Structure concurrent operations (structured concurrency) | 215 | | **Performance** | Can hurt performance if overused | Better for concurrent operations | 216 | | **Exception Handling** | Propagates exception to the caller | Cancels all children on exception, then rethrows | 217 | 218 | 219 | 220 | ### 🧭 When to Use Each 221 | 222 | #### ✅ Use `runBlocking` when: 223 | 224 | * You’re in `main()` or a unit test 225 | * You need to call suspend functions from regular code 226 | * You want to block the thread until coroutine completes 227 | 228 | #### ✅ Use `coroutineScope` when: 229 | 230 | * You're already inside a suspend function 231 | * You want concurrency without blocking threads 232 | * You need structured concurrency for launching multiple coroutines 233 | 234 | --- 235 | 236 | > 🔑 **Key Insight:** 237 | > `runBlocking` is like stopping everything to wait. 238 | > `coroutineScope` is like letting everything run smoothly, with order and efficiency. 239 | 240 | 241 |
242 | 243 | --- 244 | 245 | 246 | ## 1. Dispatchers.Main.immediate vs. Dispatchers.Main 247 | 248 | The Question ❓ 249 | 250 | "I'm collecting a StateFlow in my Android app to update a TextView. To be safe, I launch my collector on Dispatchers.Main. But when I click a button to change the state, I sometimes see a tiny visual flicker, as if the update is a frame late. I'm already on the main thread when the button is clicked, so why does dispatching to Dispatchers.Main cause a delay? How can I run the update instantly if I'm already on the right thread?" 251 | 252 | 253 | The Answer ✅ 254 | 255 | Your observation is spot on. This subtle delay is a fundamental characteristic of how Dispatchers.Main works and is a classic source of minor UI stutters. 256 | 257 | Dispatchers.Main is a dispatching dispatcher. It will always post your code block (a Runnable) to the end of the main thread's message queue (Looper). 258 | It doesn't check where the code is currently running. Even if you're already on the main thread, it effectively says, "Get in line and wait for your turn," which means your code will only run after the current frame's work is done, in the next cycle of the event loop. This is what causes that "one frame late" feeling. 259 | 260 | Dispatchers.Main.immediate is the smarter, optimizing dispatcher. It first checks if you are already on the main thread. 261 | 262 | If YES: It executes your code immediately, right then and there, without getting in line. 263 | 264 | If NO: It behaves exactly like Dispatchers.Main and posts your code to the queue to be run later. 265 | 266 | This immediate execution prevents the extra frame delay and eliminates the flicker, making it perfect for UI updates triggered from events that are already on the main thread. 267 | 268 | 269 | #### Metaphor: The Fast-Food Counter 🍔 270 | 271 | Imagine you're a cashier at a fast-food restaurant. 272 | 273 | Dispatchers.Main is like following the rules strictly: You're thirsty, so you walk away from the counter, go to the back of the customer line, and wait your turn to order a drink. 274 | It's fair, but inefficient since you were already behind the counter. 275 | 276 | Dispatchers.Main.immediate is like being efficient: You're thirsty. You glance at the line. If no customer is waiting, you just turn around and pour yourself a drink instantly. 277 | If there are customers, you put in your request and wait for your turn. You take the shortcut only when it doesn't disrupt anything. 278 | 279 | Code Example 280 | Here’s how you’d apply this in a ViewModel and Fragment. 281 | 282 | ```kt 283 | 284 | // In your ViewModel 285 | class MyViewModel : ViewModel() { 286 | private val _userName = MutableStateFlow("John Doe") 287 | val userName: StateFlow = _userName 288 | 289 | fun updateUser() { 290 | _userName.value = "Jane Smith" 291 | } 292 | } 293 | 294 | // In your Fragment 295 | class MyFragment : Fragment() { 296 | private val viewModel: MyViewModel by viewModels() 297 | 298 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 299 | super.onViewCreated(view, savedInstanceState) 300 | 301 | // The button that triggers the update 302 | myButton.setOnClickListener { 303 | viewModel.updateUser() 304 | } 305 | 306 | // --- WRONG WAY (Can cause a flicker) --- 307 | // This always posts to the queue, causing a slight delay. 308 | /* 309 | viewLifecycleOwner.lifecycleScope.launch(Dispatchers.Main) { 310 | viewModel.userName.collect { name -> 311 | nameTextView.text = name // This update runs in the *next* frame 312 | } 313 | } 314 | */ 315 | 316 | // --- RIGHT WAY (Immediate update) --- 317 | // This checks first and runs immediately if already on the Main thread. 318 | viewLifecycleOwner.lifecycleScope.launch(Dispatchers.Main.immediate) { 319 | viewModel.userName.collect { name -> 320 | nameTextView.text = name // This update runs instantly! 321 | } 322 | } 323 | } 324 | } 325 | ``` 326 | 327 | ## 2. CoroutineExceptionHandler & supervisorScope 328 | The Question ❓ 329 | 330 | "I'm using supervisorScope to run multiple independent network requests. My goal is that if one fails, it doesn't cancel the others. 331 | To log these errors for analytics, I attached a CoroutineExceptionHandler to each child launch block. But when an exception happens, my handler is never called, and the app crashes. 332 | Why is my handler being ignored?" 333 | 334 | The Answer ✅ 335 | 336 | This is a very common and tricky point of confusion in structured concurrency. 337 | Your CoroutineExceptionHandler is being ignored because of the way supervisorScope handles exception propagation. 338 | 339 | A CoroutineExceptionHandler is designed to catch uncaught exceptions. In a normal parent-child relationship, when a child fails, it cancels its parent. 340 | If nothing else catches it, the exception becomes "uncaught" and the handler is triggered. 341 | 342 | However, supervisorScope changes this behavior. When a child of a supervisorScope fails: 343 | 344 | The child immediately reports the exception to its parent (supervisorScope). 345 | 346 | The supervisorScope ignores the exception for itself (this is why it doesn't cancel its other children). 347 | 348 | Crucially, it then propagates the exception up to its own parent. 349 | 350 | Because the exception is immediately passed up the hierarchy, it is never considered "uncaught" at the child's level. 351 | The child has successfully handed off responsibility, so its personal exception handler is bypassed entirely. 352 | The exception continues up the chain until it either finds a handler on a parent scope or crashes the app. 353 | 354 | The solution is to install the CoroutineExceptionHandler on the parent coroutine that creates the supervisorScope. 355 | 356 | #### Metaphor: The Corporate Manager 👩‍💼 357 | Think of your coroutine structure as a company. 358 | 359 | The parent scope is the CEO. 360 | 361 | supervisorScope is a Manager. 362 | 363 | The child launch blocks are Employees. 364 | 365 | A CoroutineExceptionHandler on a child is an Employee's personal "oops" form. 366 | 367 | An Employee makes a mistake (throws an exception). Company policy states they must report it to their Manager. The Manager's job is to a) keep the rest of the team working and b) immediately report the failure up to the CEO. The Employee's personal "oops" form is never filled out because the error was escalated. The CEO's office is where the official error logging (the real handler) takes place. 368 | 369 | Code Example 370 | ```kt 371 | 372 | // In your ViewModel 373 | class MyViewModel : ViewModel() { 374 | fun loadAllData() { 375 | // The handler is placed on the PARENT launch block. 376 | val handler = CoroutineExceptionHandler { _, exception -> 377 | // ✅ This handler WILL be called! 378 | println("CEO's office caught: $exception") 379 | } 380 | 381 | // The parent scope has the handler 382 | viewModelScope.launch(handler) { 383 | println("CEO launched the manager...") 384 | supervisorScope { // The Manager starts their team 385 | // Employee 1: Succeeds 386 | launch { 387 | delay(300) 388 | println("Employee 1 finished work.") 389 | } 390 | 391 | // Employee 2: Fails. Has its own handler that will be IGNORED. 392 | val ignoredHandler = CoroutineExceptionHandler { _, e -> 393 | // ❌ This will NEVER be printed. 394 | println("Employee's personal form caught: $e") 395 | } 396 | launch(ignoredHandler) { 397 | println("Employee 2 is about to fail...") 398 | delay(100) 399 | throw RuntimeException("Network request failed!") 400 | } 401 | } 402 | println("Manager's scope is done.") 403 | } 404 | } 405 | } 406 | 407 | // Console Output: 408 | // CEO launched the manager... 409 | // Employee 2 is about to fail... 410 | // CEO's office caught: java.lang.RuntimeException: Network request failed! 411 | // Employee 1 finished work. 412 | // Manager's scope is done. 413 | ``` 414 | 415 | 416 |
417 | 418 | --- 419 | 420 | ## Top 10 Kotlin Coroutines Interview Questions 421 | [- Senior Android Engineer Guide](https://github.com/anandwana001/android-interview/blob/main/Top%2010%20Kotlin%20Coroutines%20Interview%20Questions%20-%20Senior%20Android%20Engineer%20Guide.pdf) 422 | 423 | 424 | 425 | ## If this Repository helps you, Show your ❤️ by buying me a ☕ below.
426 | Buy Me A Coffee 427 | 428 | 429 | ## If this repository helps you in any way, show your love :heart: by putting a :star: on this project :v: 430 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🧠 Android Engineer Interview Questions 2 | 3 | ![Android](https://img.shields.io/badge/Android-3DDC84?style=for-the-badge&logo=android&logoColor=white) 4 | ![Kotlin](https://img.shields.io/badge/kotlin-%237F52FF.svg?style=for-the-badge&logo=kotlin&logoColor=white) 5 | 6 | 7 | _Your complete companion for mastering Android, Kotlin, Jetpack Compose & System Design interviews._ 8 | 9 | Curated by [Akshay Nandwana](https://www.linkedin.com/in/anandwana001/) 10 | 11 | 12 | ## Book 1:1 Session here -> [Click Here](https://rzp.io/l/HVG4Zx4qFO) 13 | 14 | ## Complete Android Engineer Roadmap 15 | * [Roadmap 2024 - Topics](#android-roadmap-2024) 16 | * [Roadmap 2024 - Week Schedule](https://www.linkedin.com/pulse/android-engineer-interview-prep-map-akshay-nandwana-owkbf/?trackingId=CDzA28GvQN604AVSCv2itA%3D%3D) 17 | 18 | ## Detailed Question and Answers 19 | [Question and Answers](https://github.com/anandwana001/android-interview/blob/main/Detail%20Questions%20and%20Answers.md) 20 | 21 | 22 | ## Interview Contents 23 | 24 | * [Kotlin](#kotlin) 25 | * [Android](#android) 26 | * [Lifecycle](#lifecycle) 27 | * [Networking](#networking) 28 | * [Webview](#webview) 29 | * [Dependency Injection](#dependency-injection) 30 | * [Jetpack Compose](#jetpack-compose) 31 | * [Thread](#thread) 32 | * [Architecture](#architecture) 33 | * [Design Pattern](#design-pattern) 34 | * [System Design](#system-design) 35 | * [Libraries](#libraries) 36 | * [Common Question](#common-question) 37 | * [Questions from Company](#questions-from-company) 38 | * [Top 10 Kotlin Coroutines Interview Questions](#top-10-kotlin-coroutines-interview-questions) 39 | * [Kotlin Sheet 2024](#kotlin-sheet-2024) 40 | * [Jetpack Compose Sheet 2024](#jetpack-compose-sheet-2024) 41 | 42 | ## Kotlin 43 | - **What is the difference between `const val` and `val`?** 44 | - Both are used to define read-only properties, but 45 | - `const val` properties should be initialized at compile-time whereas `val` properties can be initialized at runtime 46 | - If we decompile, `const val` variable will replace with its value but `val` not, because it can be initialized at runtime 47 | - const val BASE_URL = "https://github.com" 48 | val githubHandle = "anandwana001" 49 | val repoName: String 50 | - **What is the difference between `lazy` and `lateinit`?** 51 | - `lazy` is used with `val` (Immutable) and `lateinit` is used with `var` (Mutable) 52 | - `lazy` is initialized at the time of first access, while `lateinit` is initialized after object creation 53 | - `lazy` can be used with primitive data types such as Int, Float, Double etc., whereas `lateinit` cannot be used with primitive data types 54 | - `lazy` is thread-safe by default, while `lateinit` is not thread-safe 55 | - **What is so interesting about `data class`?** 56 | - Uses to hold data 57 | - Pre-functions like `toString`, `equals`, `copy`, and `componentN` 58 | - Data classes cannot be abstract, open, sealed, or inner. 59 | - Data classes cannot extend other classes 60 | - Supports destructuring declaration 61 | - Is singleton thread-safe? vs Object? 62 | - **What are the different types of scope functions?** 63 | - Let = `T.let { R }` 64 | - lambda result (R) is the return type 65 | - can be performed on any `T` type object 66 | - lambda reference is `it` 67 | - suitable for null check 68 | - Run = `T.run { R }` 69 | - same as `let`, but mostly used in initializing an object 70 | - lambda reference is `this` 71 | - suitable for null check 72 | - With = `with(T) { R }` 73 | - if T is nullable object use `run` else use `with(T)` 74 | - lambda reference is `this` 75 | - not suitable for null check 76 | - Also = `T.also { T }` 77 | - when need to perform multiple operations in chain use `also` 78 | - lambda reference is `it` 79 | - Apply = `T.apply { T }` 80 | - when need to perform the operation on the `T` object and return the same use `apply` 81 | - lambda reference is `this` 82 | - suitable for null check 83 | - What are the different Coroutine Scopes? 84 | - How to manage series and parallel execution? 85 | - Difference between Flow/SharedFlow/StateFlow and elaborate it. 86 | - What happens if we call `.cancel()` from a coroutine scope? 87 | - What is an Init block in Kotlin? 88 | - How to choose between apply and with? 89 | - What is inline function in Kotlin? 90 | - Difference between Coroutine and Java Thread 91 | - Why Coroutines are light weight? 92 | - How does Coroutine switch context? 93 | - When to use Kotlin sealed classes? 94 | - Suspending vs Blocking in Kotlin Coroutines 95 | - What are Dispatchers and Name all of them 96 | - On which thread Dispatchers .Default execute the task or use which thread? 97 | - Dispatchers .Default vs Dispatcher .IO 98 | - What is SupervisorScope? 99 | - Exception Handling in Coroutine 100 | - Map vs FlatMap in kotlin 101 | - Singleton Pattern in Kotlin with object keyword 102 | - Collections API in Kotlin 103 | - What is Unidirectional Flow 104 | - StateFlow vs SharedFlow 105 | - Builder Pattern in Kotlin 106 | - Higher Order Functions in Kotlin 107 | - Covariance in Kotlin 108 | - Delay vs Thread.sleep? [Answer](https://www.linkedin.com/posts/anandwana001_coding-datastructures-jetpackcompose-activity-7192723727661350912-cpp-?utm_source=share&utm_medium=member_desktop) 109 | 110 | ## Android 111 | - How does Garbage collection works? 112 | - What is a dangling pointer? 113 | - Elaborate Memory Leak? 114 | - Explain fragment Lifecycle when it comes to ViewPager and sliding between different fragments. 115 | - Difference between FragmentStateAdapter and FragmentStatePagerAdapter. 116 | - Difference between Serializable and Parcelable? What are the disadvantages of Serializable? 117 | - How you could implement observable SharedPrefs or observable Databases i.e. Observe a certain key/table/query? 118 | - How does layout inflation work from xml tags to view references in memory? 119 | - What is a Thread, Handler, Looper, and Message Queue? 120 | - What are the different methods of concurrency on Android? Can you explain the difference between ExecutorService vs CachedThreadPool vs FixedThreadPool vs AsyncTasks vs HandlerThreads? 121 | - How does `ViewModel` instance provide to Activity and Fragment? How does `ViewModelProviderStore` decide when to retain the instance? 122 | - How do you inspect and solve the Jank issue? [here](https://developer.android.com/studio/profile/jank-detection) 123 | - How does the OutOfMemory happen? 124 | - How do you find memory leaks in Android applications? 125 | - What is Doze? What about App Standby? 126 | - What does `setContentView` do? 127 | - Process of creating a custom view 128 | - Deeplink understanding and architecture 129 | - Notifications 130 | - Difference between Fragment Lifecycle Observer and View Lifecycle Observer. 131 | - When should you use a Fragment rather than an Activity? 132 | - Explain the Android push notification system. 133 | - How LiveData is different from ObservableField? 134 | - What is the difference between setValue and postValue in LiveData? 135 | - What is process death? 136 | - What is ViewModelScope and How does it work internally? 137 | 138 | 139 | ### Lifecycle 140 | - How to keep a video maintain a playing state when we rotate the screen? 141 | - How many callbacks are in Fragments? 142 | - What could be the reasons why `onPause` didn't get triggered? 143 | - What kind of events trigger `onPause()` to run? 144 | - In what scenario does the "onDestory" get called directly after "onCreate"? 145 | - Which callback gets called on Activity when an AlertDialog is shown? 146 | - What's the lifecycle in PIP (Picture-in-Picture)? 147 | - What happens if you rotate the device? 148 | - Inside a viewpager (Fragment state pager adapter) what will be the lifecycle of the fragments when you swap from one tab to another? 149 | - Why onActivityCreated is now depreciated in Fragment? 150 | - Which callback should I use if I want to know when my activity came to the foreground? 151 | - When is onActivityResult called? 152 | - What does setRetainInstance do and how you can avoid it? 153 | - What callbacks trigger when a Dialog opens up? In both cases, the dialog is attached from the same activity/fragment and another activity/fragment. 154 | - What do `launchWhenCreated`, `launchWhenStarted`, and `launchWhenResumed` functions do? 155 | - Fragment Callbacks when moving from one fragment to another and coming back to prev one? 156 | - Does onCreateView get called after coming to a fragment from top fragment? 157 | - When does ViewModel not survive 158 | 159 | 160 | #### Important Lifecycle Points to Remember 161 | 162 | ##### Opening a fragment from Activity 163 | 164 | Code 165 | ``` 166 | supportFragmentManager.beginTransaction() 167 | .replace(R.id.fragment_container, FragmentA()) 168 | .commit() 169 | ``` 170 | 171 | Callbacks 172 | | | | 173 | |--|--| 174 | | MainActivity | onCreate | 175 | | FragmentA | onAttach | 176 | | FragmentA | onCreate | 177 | | FragmentA | onCreateView | 178 | | FragmentA | onViewCreated | 179 | | FragmentA | CREATED == Lifecycle.State | 180 | | FragmentA | onViewStateRestored | 181 | | FragmentA | onStart | 182 | | FragmentA | STARTED == Lifecycle.State | 183 | | MainActivity | onStart | 184 | | MainActivity | onResume | 185 | | FragmentA | onResume | 186 | | FragmentA | RESUMED == Lifecycle.State | 187 | | MainActivity | onAttachedToWindow | 188 | 189 | 190 | #### Adding a Fragment from a Fragment 191 | 192 | Code 193 | ``` 194 | parentFragmentManager.beginTransaction() 195 | .add(R.id.fragment_container, FragmentB()) 196 | .commit() 197 | ``` 198 | ``` 199 | parentFragmentManager.beginTransaction() 200 | .add(R.id.fragment_container, FragmentB()) 201 | .addToBackStack(null) 202 | .commit() 203 | ``` 204 | 205 | Callbacks 206 | | | | 207 | |--|--| 208 | | FragmentB | onAttach | 209 | | FragmentB | onCreate | 210 | | FragmentB | onCreateView | 211 | | FragmentB | onViewCreated | 212 | | FragmentB | CREATED == Lifecycle.State | 213 | | FragmentB | onViewStateRestored | 214 | | FragmentB | onStart | 215 | | FragmentB | STARTED == Lifecycle.State | 216 | | FragmentB | onResume | 217 | | FragmentB | RESUMED == Lifecycle.State | 218 | 219 | 220 | #### Replacing a Fragment from a Fragment 221 | 222 | Code 223 | ``` 224 | parentFragmentManager.beginTransaction() 225 | .replace(R.id.fragment_container, FragmentB()) 226 | .addToBackStack(null) 227 | .commit() 228 | ``` 229 | 230 | Callbacks 231 | | | | 232 | |--|--| 233 | | FragmentA | onPause | 234 | | FragmentA | onStop | 235 | | FragmentB | onAttach | 236 | | FragmentB | onCreate | 237 | | FragmentB | onCreateView | 238 | | FragmentB | onViewCreated | 239 | | FragmentB | CREATED == Lifecycle.State | 240 | | FragmentB | onViewStateRestored | 241 | | FragmentB | onStart | 242 | | FragmentB | STARTED == Lifecycle.State | 243 | | **FragmentA** | **onDestroyView** | 244 | | FragmentB | onResume | 245 | | FragmentB | RESUMED == Lifecycle.State | 246 | 247 | 248 | Code 249 | ``` 250 | parentFragmentManager.beginTransaction() 251 | .replace(R.id.fragment_container, FragmentB()) 252 | .commit() 253 | ``` 254 | 255 | Callbacks 256 | | | | 257 | |--|--| 258 | | FragmentA | onPause | 259 | | FragmentA | onStop | 260 | | FragmentB | onAttach | 261 | | FragmentB | onCreate | 262 | | FragmentB | onCreateView | 263 | | FragmentB | onViewCreated | 264 | | FragmentB | CREATED == Lifecycle.State | 265 | | FragmentB | onViewStateRestored | 266 | | FragmentB | onStart | 267 | | FragmentB | STARTED == Lifecycle.State | 268 | | FragmentA | onDestroyView | 269 | | **FragmentA** | **onDestroy** | 270 | | **FragmentA** | **onDetach** | 271 | | FragmentB | onResume | 272 | | FragmentB | RESUMED == Lifecycle.State | 273 | 274 | #### Coming Back to Previous Fragment after Adding 275 | 276 | Note: If `addToBackStack` is not used, and back stack is empty, nothing will happen when calling `popBackStack()` function 277 | 278 | Code 279 | ``` 280 | // FragmentA 281 | parentFragmentManager.beginTransaction() 282 | .add(R.id.fragment_container, FragmentB()) 283 | .addToBackStack(null) 284 | .commit() 285 | 286 | // FragmentB 287 | parentFragmentManager.popBackStack() 288 | ``` 289 | 290 | Callbacks 291 | | | | 292 | |--|--| 293 | | FragmentB | onPause | 294 | | FragmentB | onStop | 295 | | FragmentB | onDestroyView | 296 | | FragmentB | onDestroy | 297 | | FragmentB | onDetach | 298 | 299 | FragmentA is visible. No FragmentA callbacks as FragmentA is always there, neither the view nor the lifecycle get affected. 300 | 301 | #### Coming Back to Previous Fragment after Replacing 302 | 303 | 304 | Note: If `addToBackStack` is not used, and back stack is empty, nothing will happen when calling `popBackStack()` function 305 | 306 | Code 307 | ``` 308 | // FragmentA 309 | parentFragmentManager.beginTransaction() 310 | .replace(R.id.fragment_container, FragmentB()) 311 | .addToBackStack(null) 312 | .commit() 313 | 314 | // FragmentB 315 | parentFragmentManager.popBackStack() 316 | ``` 317 | 318 | Callbacks 319 | | | | 320 | |--|--| 321 | | FragmentB | onPause | 322 | | FragmentB | onStop | 323 | | **FragmentA** | **onCreateView** | 324 | | **FragmentA** | **onViewCreated** | 325 | | **FragmentA** | **CREATED** == Lifecycle.State | 326 | | **FragmentA** | **onViewStateRestored** | 327 | | **FragmentA** | **onStart** | 328 | | **FragmentA** | **STARTED** == Lifecycle.State | 329 | | FragmentB | onDestroyView | 330 | | FragmentB | onDestroy | 331 | | FragmentB | onDetach | 332 | | **FragmentA** | **onResume** | 333 | | **FragmentA** | **RESUMED** == Lifecycle.State | 334 | 335 | FragmentA view is created again. When replacing, the FragmentA view gets destroyed, `onDestroyView` gets called so when coming back it calls `onCreateView` to initialise the view again. 336 | Though, `onCreate` will not get called again. 337 | 338 | #### Lifecycle State 339 | 340 | There are 5 States: 341 | - DESTROYED 342 | - INITIALIZED 343 | - CREATED 344 | - STARTED 345 | - RESUMED 346 | 347 | ![](https://developer.android.com/static/images/guide/fragments/fragment-view-lifecycle.png) 348 | 349 | 350 | ##### Points to Remember 351 | 352 | States are based on Context/Scope you are using in. 353 | Example: 354 | ``` 355 | viewLifecycleOwner.lifecycleScope.launch { 356 | repeatOnLifecycle(Lifecycle.State.CREATED) { 357 | //... 358 | } 359 | } 360 | // viewLifecycleOwner => Lifecycle of the View 361 | // should be used between onCreateView() and onDestroyView() 362 | ``` 363 | 364 | ``` 365 | this.lifecycleScope.launch { 366 | repeatOnLifecycle(Lifecycle.State.CREATED) { 367 | //... 368 | } 369 | } 370 | // this => Lifecycle of Fragment or Activity 371 | ``` 372 | 373 | | | | 374 | |--|--| 375 | | CREATED | - listen in `onDestroyView` (if not View lifecycle) and in `onStop`, `onSavedInstance` too | 376 | | STARTED | - listen in `onStart`, `onPause` | 377 | | RESUMED | - listen in `onResume` | 378 | | DESTROYED | - listen in `onDestroyView` (if View lifecycle) and in `onDestroy` | 379 | | CREATED | - listen in `onViewStateRestored` (if View lifecycle) | 380 | | CREATED | - listen in `onCreate`, `onCreateView`, `onViewCreated`, `onViewStateRestored` (if not View lifecycle) | 381 | 382 | 383 | #### Examples 384 | 385 | - if state CREATED and app moves to background, it will listen. Hence, Avoid UI work here 386 | - use state CREATED if need to complete action even after Fragment View destroy 387 | - 388 | 389 | ### Networking 390 | - What is the role of OkHttp and Retrofit? 391 | - What design pattern does Retrofit use? 392 | - How would optimize the handling of access token expiration? How would you handle a retry network call when the API fails? (Custom Interceptor response) 393 | 394 | 395 | ### Webview 396 | - What are the problems around security when dealing with `WebView`? 397 | - How to interact or make connections with JavaScript? 398 | 399 | 400 | ### Dependency Injection 401 | - Provides vs binds 402 | - Subcomponent vs. component dependency, what is the difference under the hood 403 | - What is a subcomponent and what is its use? How do you use qualifiers or how would you provide different instances of a class with the same data type? Constructor Injection V/s Method Injection? What is the scope? Singleton Annotation? 404 | - What is Circular dependency in dagger? and how to resolve it 405 | - What's interesting about Hilt? 406 | - Did you use Koin? What are your thoughts on it? 407 | 408 | 409 | ### Jetpack Compose 410 | - How to launch a coroutine from a composable function? - [LaunchedEffect](https://www.droidcon.com/2021/10/28/jetpack-compose-side-effects-ii-remembercoroutinescope/) 411 | - How to launch a coroutine from a non-composable function, but tied to composition? - [rememberCoroutineScope()](https://www.droidcon.com/2021/10/28/jetpack-compose-side-effects-ii-remembercoroutinescope/) 412 | - What is recomposition? [Recomposition](https://developer.android.com/jetpack/compose/mental-model#recomposition) 413 | - **What is `remember` in compose?** 414 | - A composable function to remember the value produced by a calculation only at the time of composition. It will not calculate again in recomposition. 415 | - Recomposition will always return the value produced by composition. 416 | - Whole Compose is based on the concept of `Positional Memoization` 417 | - At the time of recomposition, `remember` internally calls a function called `rememberedValue()` whose work is to look into the `slotTable` and compare if the previous value and the new value have any difference, if not return, else update the value 418 | - Why and when to use `remember {}`? 419 | - Difference between `LazyColumn` and `RecyclerView`? 420 | - What is AndroidView in compose? 421 | - What is the lifecycle of composeables? [Lifecycle](https://developer.android.com/jetpack/compose/lifecycle) 422 | - How to avoid recomposition of any composable, if the state is not changed? [Smart Recomposition](https://developer.android.com/jetpack/compose/lifecycle#add-info-smart-recomposition) 423 | - What are stable types that can skip recomposition? 424 | - What is State? 425 | - What is MutableState and how does recomposition happen? 426 | - How to retain State across recomposition and configuration changes? 427 | - Difference between Stateless and Stateful composeables? 428 | - What are your thoughts on flat hierarchy, constraint Layout in compose vs. the older view hierarchy in xml 429 | - Difference b/w remember and LaunchedEffect 430 | - Does re-composition of `ComposeItem1` bring any effect on `ComposeItem2`? If yes, then how? 431 | - `ComposeParent() { ComposeItem1 {} ComposeItem2() {...} } ` 432 | - What is `CompositionLocal`? 433 | - Custom views in compose 434 | - Canvas in Compose 435 | - What are the benefits of Jetpack Compose? 436 | - How does Jetpack Compose integrate with existing Android frameworks and libraries? 437 | - What are the best practices for performance optimization in Jetpack Compose? 438 | - How is navigation handled in Jetpack Compose? 439 | - What is Strong Skipping Mode? [Answer](https://www.linkedin.com/posts/anandwana001_coding-datastructures-jetpackcompose-activity-7193437801365823488-SlVT?utm_source=share&utm_medium=member_desktop) 440 | 441 | 442 | ## Thread 443 | - Different types of threads? 444 | - Difference between different types of thread? 445 | - Thread <-> Handler <-> looper 446 | - UI vs Background Thread 447 | - How do you know when some process if blocking a UI thread? 448 | 449 | ## Architecture 450 | - What are SOLID principles? 451 | - What is MVVM? 452 | - Brief about Android Architecture. 453 | - MVP vs MVVM? 454 | - Is there any issue in the Presenter in the MVP? 455 | - Clean Architecture 456 | - MVVM vs MVI 457 | - What is Clean Architecture in MVVM 458 | - What are Provides and Binds in your Dagger library 459 | 460 | 461 | ## Design Pattern 462 | - What is SOLID principle? 463 | - What are different design patterns you know about? 464 | - What is a creational pattern? 465 | - What is a structural pattern? 466 | - What is a behavioral pattern? 467 | - Create Singleton Pattern without Kotlin default implementation 468 | - Create Observer Pattern 469 | - Create Adapter Pattern 470 | - How to make a Singleton Pattern Thread Safe? 471 | - What is Dependency Inversion 472 | - Write a real-life example of Dependency Injection without using any library 473 | - Explain how Android Architecture components (ViewModel, LiveData, etc.) utilize design patterns behind the scenes 474 | 475 | ## System Design 476 | - Design Image Loading Library 477 | - Design Image Downloading Library 478 | - Design LRU Cache 479 | - Design a real-time Twitter feed timeline. How will you structure the backend? Will you use WebSocket or REST for this use case? Justify. 480 | - Design Networking Library 481 | - Design Checkout Screen 482 | - Design Error handling Structure 483 | - REST <-> Web Sockets 484 | - Implement caching mechanism 485 | - Build an offline-first app 486 | - Design Analytics Library 487 | 488 | 489 | ## Libraries 490 | - How does Glide internally work? 491 | - How does retrofit work internally? 492 | - ViewModel internal working 493 | - How will you choose between Dagger 2 and Dagger-Hilt? 494 | 495 | ## Common Question 496 | - `String` vs `StringBuilder` 497 | - `==` vs `.equals`? 498 | - `===` vs `==`? 499 | - Java OOP concepts 500 | 501 | 502 | ## Questions from Company 503 | | Company | Questions | 504 | | --- | --- | 505 | | Booking.com | | 506 | | Spotify | | 507 | | PhonePe | | 508 | | Paytm | | 509 | | Meesho | | 510 | 511 | 512 | ------ 513 | 514 | ## Android Roadmap 2024 515 | | Topics | Sub-Topics | 516 | | --- | --- | 517 | | Programming Languages |
  • Kotlin
  • Java
  • | 518 | | Android Architecture | ![image](https://developer.android.com/static/guide/platform/images/android-stack_2x.png) | 519 | | Runtime |
  • Dalvik Virtual Machine
  • Android Runtime
  • | 520 | | Android Manifest |
  • Package
  • Application Id
  • | 521 | | Permissions |
  • Install-time Permissions
  • Special Permissions
  • Runtime Permissions
  • Permissions Groups
  • | 522 | | Android Build |
  • APK
  • AAB
  • | 523 | |Thread|
  • Processes
  • Threads
  • Inter Process Communication
  • Handlers
  • Loopers
  • Message Queue
  • UI Thread
  • Background Thread
  • Heap & Stack
  • | 524 | | Fundamental Components |
  • Activity
  • Services
  • Broadcast Receiver
  • Content Provider
  • | 525 | | Intent |
  • Implicit Intent
  • Explicit Intent
  • Intent Filters
  • Intent Flags
  • | 526 | |Activity|
  • Activity Lifecycle
  • Tasks and Back Stacks
  • Bundles
  • Parcelables
  • Recent Screens
  • App Shortcuts
  • Context
  • | 527 | |Services|
  • Service Lifecycle
  • Foreground Service
  • Background Service
  • Bound Service
  • AIDL
  • Job Scheduler
  • WorkManager
  • IntentService
  • | 528 | |Broadcast Receiver|
  • Pub-Sub
  • System Broadcast
  • Permissions
  • Security
  • | 529 | |Content Provider|
  • Content Resolver
  • Cursor
  • MIME Types
  • Contracts
  • | 530 | |Data Storage|
  • App Specific Storage
  • Shared Storage
  • Preferences
  • Database
  • Scoped Storage
  • LRU Cache
  • SQLite
  • ROOM
  • Data Store
  • | 531 | |Fragments|
  • Fragment Lifecycle
  • Dialog Fragment
  • Fragment Transactions
  • Fragment Manager
  • View Lifecycle
  • BackStack
  • Fragment-Activity Communication
  • Fragment-Fragment Communication
  • | 532 | |Navigation Component |
  • Host
  • Graph
  • Controller
  • Back Stacks
  • Destinations
  • Deeplink
  • | 533 | |Jetpack Components|
  • ViewModel
  • LiveData
  • Paging
  • Lifecycle
  • WorkManager
  • Data Binding
  • | 534 | |UI |
  • XML
  • Jetpack Compose
  • | 535 | |Jetpack Compose|
  • Composition
  • ReComposition
  • State Hoisting
  • Remember
  • RememberSaveable
  • Side Effects
  • LaunchedEffect
  • DisposableEffect
  • DerivedStateOf
  • SnapshotFlow
  • CompositionLocal
  • Theming
  • Modifier
  • Layouts
  • Box/Column/Row
  • Image/painter
  • Coil
  • LazyColumn/LayRow
  • Text/Button/ other ui components
  • | 536 | |Testing|
  • UI Testing
  • Unit Testing
  • Espresso
  • Robolectric
  • Mockk
  • | 537 | |Debugging|
  • Logcat
  • Timber
  • Break Points
  • Chucker
  • Charles
  • LeakCanary
  • | 538 | |Libraries|
  • Retrofit
  • OkHttp
  • Glide
  • Material3
  • Hilt
  • Dagger
  • Retrofit
  • | 539 | |Benchmark|
  • Micro Benchmark
  • Macro Benchmark
  • | 540 | |Static Analysis|
  • Ktlint
  • Detekt
  • Android Lint
  • | 541 | |GitHub Actions|
  • Pipeline
  • Build Generation
  • Workflow
  • | 542 | |Gradle|
  • Commands
  • Groovy
  • | 543 | |Common Errors|
  • ANR
  • App Crash
  • Fatal Error
  • OOM
  • ArrayOutOfBound
  • | 544 | |Proguard|
  • Obfuscation
  • Keep
  • | 545 | |Code Architecture|
  • MVP
  • MVVM
  • MVI
  • Modularization
  • Design Patterns
  • Network Layer
  • Data Layer
  • UI Layer
  • Domain/Repository/...
  • | 546 | |Firebase |
  • Crashlytics
  • Remote Config
  • A/B Testing
  • | 547 | |App Release|
  • App Release Process
  • App Distribution
  • Google Play Console
  • App Review/Ratings
  • App Size
  • App Policies
  • | 548 | 549 | 550 | ------ 551 | 552 | ## Top 10 Kotlin Coroutines Interview Questions 553 | [- Senior Android Engineer Guide](https://github.com/anandwana001/android-interview/blob/main/Top%2010%20Kotlin%20Coroutines%20Interview%20Questions%20-%20Senior%20Android%20Engineer%20Guide.pdf) 554 | 555 | 556 | ------ 557 | 558 | ## Kotlin Sheet 2024 559 | ![](https://github.com/anandwana001/android-interview/blob/main/Kotlin%20Sheet%202024.gif) 560 | 561 | ## Jetpack Compose Sheet 2024 562 | ![](https://github.com/anandwana001/android-interview/blob/main/Jetpack%20Compose%202024.gif) 563 | 564 | 565 | ## Contributing Guidelines 566 | What interesting questions do you face while giving an interview for an Android Engineer role (any level)? Let's open a PR. 567 | 568 | ## If this Repository helps you, Show your ❤️ by buying me a ☕ below.
    569 | Buy Me A Coffee 570 | 571 | 572 | ## If this repository helps you in any way, show your love :heart: by putting a :star: on this project :v: 573 | --------------------------------------------------------------------------------