Career Development

Advanced Android Engineering: 15 Architecture & Flow Questions

P
By Principal Android Lead
June 27, 2026 5 min read
Advanced Android Engineering: 15 Architecture & Flow Questions

Modern Android systems demand deep architectural knowledge. Scaling codebases requires clean dependency setups, reactive Flow transformations, secure device cryptography, and precise performance profiling metrics. This article reviews 15 advanced, unique interview questions.

Q1. How do you implement custom Canvas drawing in Jetpack Compose?

Answer:

Use the Canvas composable which exposes a DrawScope. Inside, execute vector rendering calls like drawRect, drawCircle, drawLine, or custom paths:

Canvas(modifier = Modifier.fillMaxSize()) {
    drawCircle(color = Color.Blue, radius = 100f)
}

Q2. Explain Flow flattening operations: flatMapConcat, flatMapMerge, and flatMapLatest.

Answer:

  • flatMapConcat: Transforms and executes inner Flows sequentially. Wait for the current inner Flow to complete before collecting the next one.
  • flatMapMerge: Collects from multiple inner Flows concurrently, merging emissions into a single stream.
  • flatMapLatest: Collects from the latest Flow. If a new outer value emits, it cancels the previous inner Flow collection immediately.

Q3. What is the difference between Kotlin Flow and Channel?

Answer:

  • Flow: A cold, pull-based stream. Executed lazily; no work occurs until terminal operators (like `collect()`) are called.
  • Channel: A hot, push-based communication pipeline (similar to BlockingQueue). Producers send values independently of active subscribers.

Q4. Compare Dagger 2 Component Dependencies vs. Subcomponents.

Answer:

  • Component Dependencies: Used when components need to be loosely coupled. Child components explicitly import only declared bindings from parent components.
  • Subcomponents: Highly coupled parent-child relationships. Subcomponents inherit the entire object graph of the parent component automatically.

Q5. What are the Stable and Immutable annotations in Compose?

Answer:

They inform the Compose compiler of data stability rules to prevent redundant recompositions:

  • @Immutable: Guarantees that all public properties of the annotated class will never change after instantiation.
  • @Stable: Indicates that properties may change, but Compose will be notified of all state modifications (e.g. through mutable state objects).

Q6. How do stateIn and shareIn convert cold flows to hot flows?

Answer:

  • stateIn: Converts a Flow to a hot StateFlow, caching the latest emitted value and requiring an initial default value.
  • shareIn: Converts a Flow to a hot SharedFlow, broadcasting values to multiple subscribers concurrently without caching state unless a replay value is specified.

Q7. What is the Jetpack App Startup library?

Answer:

It provides a high-performance way to initialize libraries at application startup. Instead of having separate ContentProviders for each dependency (which slows app cold starts), App Startup shares a single ContentProvider to coordinate initialization orders.

Q8. What is RemoteMediator inside Paging 3?

Answer:

RemoteMediator coordinates loading page bounds between a network source and a local SQLite database (via Room). When local cached database records are exhausted, it automatically calls backend endpoints, stores the results in SQLite, and displays updates dynamically via Room observers.

Q9. Compare Preferences DataStore vs. Proto DataStore.

Answer:

  • Preferences DataStore: Stores key-value pairs (similar to SharedPreferences) but runs asynchronously using Kotlin Coroutines on disk threads.
  • Proto DataStore: Stores typed objects using Protocol Buffers, providing type safety and preventing runtime serialization crashes.

Q10. How does LeakCanary find memory leaks?

Answer:

LeakCanary hooks into the Android lifecycle. When an activity/fragment is destroyed, it wraps it in a weak reference (WeakReference) and monitors garbage collection cycles. If the object remains in memory after a GC call, it runs a heap dump analysis (`Shark`) to find the shortest reference path to the garbage collection root.

Q11. How do you generate and store cryptographic keys using Android Keystore?

Answer:

Use KeyGenParameterSpec. Generate symmetric keys (AES) or asymmetric key pairs (RSA) securely within hardware-backed security modules:

KeyGenerator.getInstance("AES", "AndroidKeyStore").apply {
    init(KeyGenParameterSpec.Builder("my_key_alias", ...).build())
    generateKey()
}

Q12. What are Dynamic Feature Modules?

Answer:

They let you isolate features that are not required at initial app install. Dynamic features are built as independent modules, and downloaded on-demand using the Google Play Core library when requested by the user, reducing the initial APK footprint.

Q13. What is Jetpack Macrobenchmark?

Answer:

It measures real-world app interactions (like cold start speed or frame rendering speeds) directly on the target device, simulating user scroll actions to detect frame drops and compile optimization configurations (Baseline Profiles).

Q14. How do you construct a custom RecyclerView LayoutManager?

Answer:

Subclass RecyclerView.LayoutManager and override generateDefaultLayoutParams(). Implement onLayoutChildren(), which calculates visible scroll coordinates and lays out child items from the recycler pool.

Q15. Compare Job vs. SupervisorJob in Coroutines.

Answer:

  • Job: Cancellations propagate bidirectionally. If a child job throws an exception, the parent and all sibling jobs are canceled immediately.
  • SupervisorJob: Cancellations propagate unidirectionally (downward). If a child job fails, the parent continues executing and sibling jobs remain unaffected.

Link copied to clipboard!