Android Developer Interview Questions & Answers
Interview Q&A for Android and Kotlin developers, with real code examples. Covers Jetpack Compose, Coroutines, Hilt, Flow, StateFlow, R8, architecture patterns, and system design. By skydoves, Google Developer Expert in Android, Kotlin, and Firebase.
A Bitmap looks like an ordinary Java object, but most of its weight lives somewhere the garbage collector cannot directly see. A single full screen photo can occupy tens of megabytes of pixel data, and where that data…
A ContentProvider is usually described as a way to share data between apps, but it has a second role that explains a surprising amount of library behavior: the system creates and calls onCreate() on every provider…
Kotlin Coroutines use structured concurrency to propagate exceptions through the Job hierarchy. When a child coroutine fails, the exception travels upward to the parent, which cancels all remaining siblings and fails…
When a user taps your app icon and nothing is in memory, the system creates a new process, loads the Application class, instantiates ContentProviders, calls Application.onCreate(), then launches the target Activity and…
R8 is the default code shrinker, optimizer, and obfuscator for Android applications. It runs at build time, taking compiled bytecode and producing a smaller, faster APK by removing unused code, applying optimizations…
Every frame in Compose goes through three ordered phases: Composition, Layout, and Drawing. Composition reexecutes composable functions to produce or update the node tree. Layout measures each node and assigns its…
Kotlin Coroutines handle cancellation through a cooperative mechanism built on top of structured concurrency. Cancellation does not stop a coroutine by force. Instead, it propagates a signal through the Job hierarchy,…
Kotlin Flow enforces a strict context preservation rule: every emission must occur in the same coroutine context where the flow is collected. This invariant is fundamental to Flow's design, ensuring thread safety…
Hilt is a compile time dependency injection framework for Android built on top of Dagger. Its most consequential architectural decision is a two phase compilation model that splits annotation processing into an…
Coroutine dispatchers are the mechanism through which Kotlin Coroutines control which thread or thread pool a coroutine executes on. They achieve this by implementing the ContinuationInterceptor interface, which allows…
Kotlin suspend functions appear sequential in source code, but the compiler transforms them into state machines driven by Continuation-Passing Style (CPS). This transformation is the foundation of the entire coroutine…
Android's Toast is one of the most commonly used UI components, yet its internal architecture reveals fundamental concepts about how the Android framework manages windows, system services, and threading. A Toast is not…
Kotlin's inline keyword resolves a fundamental tension in JVM language design: how to offer high level abstractions like higher order functions without paying the runtime cost of anonymous class allocation and virtual…
Kotlin coroutines decouple what a coroutine does from where it executes. The "where" is determined by the coroutine dispatcher, a component that assigns coroutine continuations to threads. Two dispatchers dominate…
State hoisting is one of the foundational patterns in Jetpack Compose for building predictable, reusable, and testable UI components. The idea is straightforward: move state ownership out of a composable and into its…
Webtoon reader applications present one of the most demanding image-loading challenges on mobile platforms. Users scroll through vertically continuous strips of high-resolution artwork, often spanning dozens of…
Android applications that go beyond simple prototypes require a clear separation of concerns, predictable data flow, and a layered structure that scales with feature growth. Google's official architecture guidance…
Building a real time chat screen requires coordinating persistent network connections, local persistence, optimistic UI updates, and efficient list rendering within a modern Android architecture. The chat domain is…
Kotlin coroutines provide two primary coroutine builders for starting concurrent work: launch and async. While both create new coroutines within a structured concurrency scope, they serve fundamentally different…
UI jank occurs when the main thread cannot complete its work within a single frame deadline, causing visible stuttering or dropped frames for the user. On modern Android devices targeting 60, 90, or 120 Hz refresh…
Every Android Activity follows a strictly defined lifecycle managed by the ActivityManager service and the ActivityThread class in the framework. When the system brings an Activity to the foreground, pauses it for a…
The APK Analyzer in Android Studio provides a way to inspect the contents of an APK, AAB, or ZIP file without reverse-engineering. While developers commonly use it to check file sizes and DEX method counts, one of its…
Every composable function in Jetpack Compose follows a lifecycle defined by three events: entering the Composition, recomposing zero or more times, and leaving the Composition. Unlike the traditional Android View…
Jetpack Compose uses the stability of a composable's parameters to decide whether it can skip recomposition when the parent recomposes. A stable type is one whose changes Compose can reliably detect through equality…
Starting with Android 10 (API 29), apps running foreground services are generally restricted from launching activities directly from the background. Even though a foreground service indicates an ongoing operation the…
Threads and coroutines both enable concurrent execution, but they differ fundamentally in how they are managed, how they handle blocking, and what resources they consume. Threads are operating system level constructs…
In a UI state production pipeline, it is common to combine one-shot operations like deleting an item or fetching a single record with stream-based sources like live repository updates. The recommended strategy is to…
When items in a LazyColumn change order, get added, or get removed, Jetpack Compose needs a way to keep each item's remembered state correctly associated with it. Item keys provide this association. Without them,…
Transient UI messages like Snackbars often originate from ViewModel logic, such as a failed network request or a completed action. In a Unidirectional Data Flow (UDF) architecture, these messages should be represented…
Baseline Profiles are a form of Profile Guided Optimization (PGO) that improve Android app performance from the first launch by enabling Ahead of Time (AOT) compilation of user facing code paths. Without them, Android…
Build Analyzer is a tool in Android Studio that helps developers detect and resolve build performance issues by surfacing detailed data about which Gradle tasks and plugins contribute most to build time. By comparing…
Jetpack Compose offers two approaches to text input: value-based text fields and state-based text fields. They differ in how they manage input state, handle text transformations, configure line limits, and support…
Jetpack Compose provides CompositionLocal as a mechanism to pass data implicitly down the composition tree without threading it through every composable parameter. There are two factory functions for creating a…
Jetpack Compose uses a semantics system to define the meaning of UI elements beyond their visual appearance. This system serves both accessibility services and the testing framework, providing a structured way to…
Kotlin Coroutines provide two distinct concurrency primitives for passing data between coroutines: Channel and Deferred. A Deferred<T> represents a single future result, while a Channel<T> represents a stream of values.…
Jetpack Compose provides multiple ways to create custom modifiers, each offering different trade-offs between simplicity, flexibility, and performance. Selecting the right approach depends on whether you need access to…
In Android architecture, the UI layer serves two purposes: rendering application data on screen and acting as the interface for user interaction. How state flows through this layer determines the predictability and…
Jetpack Compose is structured as a layered, modular framework rather than a single monolithic toolkit. Each layer builds on top of lower level components, providing increasing levels of abstraction and convenience while…
Kotlin coroutines provide a structured and lightweight solution for asynchronous programming in Android by enabling non blocking code execution while maintaining readability. They allow developers to perform background…
A unit test verifies the correctness of a single "unit" of code, usually a function, class, or small component, by isolating it from the rest of the system. In Android development, unit tests are typically used to check…
Preserving UI state in Jetpack Compose is essential for ensuring a smooth user experience, especially during configuration changes or system initiated process death. Depending on whether the state serves UI logic or…
In Android development, maintaining clean, consistent, and error free code is essential for app stability and long term maintainability. Lint is a static code analysis tool built into Android Studio that helps…
Android provides several mechanisms to handle long running background tasks while ensuring optimal resource usage and compliance with modern OS restrictions. The appropriate method depends on the nature of the task, its…
In Jetpack Compose, recomposition is the process that updates the UI when observable state changes. It is a central part of Compose's reactive programming model and one of the key mechanisms in the composition…
Kotlin provides several extension functions for extracting subsets or specific parts of collections. These functions enable efficient data retrieval while keeping the original collections unchanged. Understanding which…
ViewStub is a lightweight and invisible placeholder view used to defer the inflation of a layout until it is explicitly needed. It improves performance by avoiding the overhead of inflating views that may not be…
Jetpack Compose provides a declarative animation system that enables smooth transitions between UI states. With built in APIs, developers can animate composable visibility, content changes, size adjustments, and…
A paging system optimizes how data is loaded and displayed when dealing with large datasets. By fetching data in smaller, manageable chunks, it ensures smooth app performance and a better user experience. Loading…
runBlocking is a coroutine builder in Kotlin that bridges regular blocking code and suspend functions. It blocks the current thread until the coroutine execution is complete. While it may seem convenient for calling…
Invalidation refers to the process of marking a View as needing to be redrawn. It is a fundamental mechanism in the Android View system that updates the UI when changes occur. When a View is invalidated, the system…
Android applications are distributed using two primary formats: APK (Android Package) and AAB (Android App Bundle). The APK is the traditional installable format that contains all resources for all device…
A higher order function is a function that takes another function as a parameter, returns a function, or both. This concept is central to Kotlin's support for functional programming and enables patterns such as…
When displaying hundreds or thousands of items in Jetpack Compose, standard layouts like Column compose all children at once, regardless of visibility. This causes unnecessary memory consumption and composition…
Kotlin properties provide a concise syntax for declaring fields with accessors. Behind this syntax, two mechanisms manage the actual storage of property values: backing fields and backing properties. A backing field is…
Understanding the lifecycle callback order when navigating between two Activities is essential for managing resources, saving state, and avoiding visual glitches during transitions. The Android system interleaves the…
Jetpack Compose does not include a built in API for loading images from network URLs. This is by design, because network image loading involves complex concerns such as HTTP fetching, bitmap decoding, memory and disk…
The produceState function creates a State object whose value is produced by a coroutine launched within the composition. It bridges asynchronous operations like network requests, database queries, or long running…
Optimizing an Android application's size directly affects download conversion rates, installation success on storage constrained devices, and update adoption. Multiple strategies work together to minimize the final APK…
Kotlin provides four visibility modifiers that control the accessibility of classes, interfaces, functions, and properties: public, private, protected, and internal. These modifiers define clear boundaries for code…
Baseline Profiles are a performance optimization feature that reduces app startup time and improves runtime execution by providing pre compiled code information to the Android Runtime (ART). Instead of relying on…
The val keyword in Kotlin is commonly mistaken for a guarantee of immutability. In practice, val only ensures that a reference cannot be reassigned after initialization. It does not prevent modification of the object…
Box is a foundational layout composable in Jetpack Compose that stacks its children on top of each other within a common parent. Unlike Column and Row, which arrange children sequentially along a single axis, Box…
When working with APIs secured by OAuth, handling token expiration and refresh is a critical part of the networking layer. OkHttp provides two mechanisms for this: the Authenticator interface and Interceptor. The…
A value class is a special kind of class that wraps a single value and is optimized by the compiler to avoid unnecessary object allocation at runtime. While a value class provides type safety and semantic clarity at the…
The AndroidManifest.xml file is a required configuration file in every Android project. It declares essential information about the application to the Android operating system, acting as a bridge between the app and the…
Collecting Flow inside Composable functions is a common pattern for handling UI state and reacting to data changes. If not managed properly, it can lead to memory leaks, unnecessary background work, or excessive…
The flowOn operator changes the coroutine context for upstream operations in a Kotlin Flow without affecting downstream collectors. It is the primary mechanism for moving expensive computations, IO operations, or…
Context is one of the most frequently used objects in Android development. It provides access to application resources, system services, databases, shared preferences, and the file system. However, improper usage of…
Kotlin provides a structured set of collection types for managing groups of elements. Collections are divided into two categories: read only collections that expose only access operations and mutable collections that…
snapshotFlow is a bridge between Compose's state observation system and Kotlin's Flow API. It converts state reads that happen inside a Compose Snapshot into a cold Flow that emits whenever the observed state changes.…
Kotlin supports defining classes inside other classes, and the behavior depends on whether the inner keyword is used. A nested class (without inner) does not hold a reference to its enclosing class and behaves like a…
Android is an open source operating system based on the Linux kernel, developed and maintained by Google. It is designed primarily for touchscreen mobile devices like smartphones and tablets, but it also powers a wide…
LiveData is an observable data holder class from Android's Jetpack Architecture Components. It is lifecycle aware, meaning it only delivers updates to observers that are in an active lifecycle state such as STARTED or…
Composition is the process Jetpack Compose uses to build and manage the UI tree by executing Composable functions. When a Composable function runs for the first time, Compose records it in an internal data structure and…
Android provides several mechanisms for storing and persisting data locally, each designed for different data shapes and access patterns. Choosing the right storage solution depends on whether the data is simple key…
Kotlin handles null values with a null safety system, but some behaviors around null can still surprise developers. One common interview topic is what happens when you evaluate null + null. The result is not a compiler…
Jetpack Compose is a declarative UI framework where developers describe what the UI should look like for a given state rather than issuing step by step instructions to mutate views. The framework observes state changes…
ActivityManager is a system service in Android that provides access to information about running activities, tasks, processes, and memory state on the device. It serves as the primary API for querying system level…
Android provides two specialized view classes for rendering content outside the normal view drawing pipeline: SurfaceView and TextureView. Both enable offscreen rendering for use cases like video playback, camera…
Android applications go through a unique compilation and execution pipeline before running on a device. The Android Runtime (ART), its predecessor Dalvik, and the Dex Compiler each play a role in transforming…
Android's build system uses build variants and product flavors to produce multiple versions of an application from a single codebase. Build types control how the application is compiled and packaged, while product…
Kotlin functional interfaces, also called Single Abstract Method (SAM) interfaces, allow an interface with exactly one abstract method to be instantiated using a lambda expression. This mechanism reduces boilerplate…
Kotlin Multiplatform (KMP) is a framework by JetBrains that enables sharing code across multiple platforms while preserving access to native APIs where platform specific behavior is needed. Unlike cross platform…
A Bundle is a key value data structure in Android used for passing data between components such as activities, fragments, and services. It serializes data into a format the operating system can transmit across process…
CompositionLocal is a mechanism in Jetpack Compose for passing data implicitly down the composition tree without threading it through every composable function as a parameter. It provides scoped access to values like…
Offline first design ensures that an application functions without an active network connection by relying on locally stored data and synchronizing with a remote server when connectivity is restored. This approach…
Scope functions are a set of functions in the Kotlin standard library that execute a block of code within the context of an object. They reduce boilerplate, improve readability, and provide a structured way to configure…
Kotlin provides two distinct operators for comparing objects: structural equality (==) and referential equality (===). Structural equality checks whether two objects have equivalent content, while referential equality…
The Android file system is a structured environment built on top of the Linux kernel that manages and organizes data storage across the device. It provides isolated storage spaces for each application, shared…
A lambda expression is an anonymous function that can be treated as a value. You can pass it as an argument to another function, return it, or store it in a variable. Lambdas are a foundational feature of Kotlin's…
In Jetpack Compose, composables can be categorized as stateful or stateless depending on whether they manage their own state internally or receive it from an external source. Understanding this distinction is…
Context is the base class that provides access to application resources, system services, and component lifecycle information in Android. Every Activity, Service, Application, and BroadcastReceiver either is a Context…
The Application class is the base class for maintaining global application state in Android. It is instantiated before any Activity, Service, BroadcastReceiver, or ContentProvider and remains alive for the entire…
Jetpack Compose provides mutableStateListOf and mutableStateMapOf as observable collection types that integrate with the snapshot state system. Unlike regular MutableList or MutableMap, modifications to these…
A race condition occurs when the correctness of a program depends on the relative timing of concurrent operations accessing shared mutable state. Two or more threads or coroutines read and write the same data without…
Android manages memory through a garbage collection mechanism that automatically reclaims objects no longer referenced by the application. The Dalvik and ART runtimes track object reachability and free unreachable…
Jetpack Compose provides derivedStateOf as a state management utility that creates a state object whose value is computed from other observable states. The key benefit is that the derived computation only re-executes…
The Factory Pattern is a creational design pattern that delegates object construction to a dedicated method or class instead of calling constructors directly. In Kotlin, the pattern takes several idiomatic forms,…
SparseArray is an Android specific data structure that maps integer keys to object values, designed as a memory efficient alternative to HashMap<Integer, Object>. It avoids the autoboxing overhead of converting…
Kotlin's Flow API provides two fundamentally different emission models. A cold flow produces values only when a collector is present, starting fresh for each new collector. A hot flow emits values independently of…
Kotlin extensions let you add new functions and properties to existing classes without modifying their source code or using inheritance. The compiler resolves extension calls statically, meaning they do not actually…
An LRU (Least Recently Used) cache is a fixed capacity data structure that evicts the least recently accessed entry when the capacity is exceeded. It provides O(1) time complexity for both retrieval and insertion by…
Recomposition is the process by which Jetpack Compose re executes composable functions when their input state changes. Rather than rebuilding the entire UI tree, the Compose runtime tracks which composable functions…
Kotlin's coroutines library provides two hot flow types for sharing data across multiple collectors: StateFlow and SharedFlow. Both emit values regardless of whether any collector is active, but they differ in how they…
The AndroidManifest.xml file is a required configuration file at the root of every Android application module. It declares the application's components, permissions, hardware requirements, and metadata to the Android…
Jetpack Compose uses two distinct concepts to position children inside layout containers: Arrangement controls spacing along the main axis, and Alignment controls positioning along the cross axis. Confusing the two is a…
The Builder Pattern is a widely used creational design pattern that constructs complex objects step by step. Instead of relying on multiple constructors with varying parameter lists, a builder object accumulates…
A companion object in Kotlin is a singleton object declared inside a class using the companion object keyword. Its members belong to the class itself rather than to any instance, serving a role similar to static members…
Configuration changes occur when the device's state shifts in a way that affects available resources. Screen rotation, locale switches, dark mode toggles, and font size adjustments all qualify. By default, the Android…
A Domain Specific Language (DSL) in Kotlin is a programming style that uses extension functions, lambdas with receivers, and other language features to create APIs that read like a custom mini language tailored to a…
ANR (Application Not Responding) is the Android system's response to an application that blocks its main thread for too long. When the main thread cannot process input events or BroadcastReceiver.onReceive() within the…
A side effect in Jetpack Compose is any operation that escapes the scope of a composable function and persists beyond recomposition. Composables are intended to be pure functions of their inputs: given the same state,…
The Observer pattern establishes a one to many dependency between objects so that when one object (the subject) changes state, all its dependents (observers) are notified and updated automatically. In Android, this…
The Repository pattern is a design pattern that abstracts data access behind a clean API, decoupling the rest of the application from the specifics of how data is fetched, cached, and persisted. In Android, repositories…
SaveableStateHolder is a Compose interface that preserves and restores the rememberSaveable state of composable subtrees independently, keyed by a unique identifier. While rememberSaveable persists individual values…
The Android Activity lifecycle defines the sequence of states an Activity transitions through from creation to destruction. The system invokes specific callback methods at each transition, giving the application an…
State hoisting is a pattern in Jetpack Compose where you move state ownership from a child composable up to its caller. The child becomes stateless, receiving its current value and an event callback as parameters. This…
Kotlin Coroutines and JVM threads both enable concurrent execution, but they operate at fundamentally different levels of abstraction. Threads are OS managed constructs that consume real kernel resources, while…
Fragments have their own lifecycle that is closely tied to, but distinct from, the lifecycle of the host Activity. A Fragment transitions through creation, view creation, visibility, interactivity, and destruction…
Every Android View goes through a series of stages from creation to destruction. The system calls specific methods as the View is attached to a window, measured, laid out, drawn, and eventually detached. Understanding…
Android's View system allows you to create custom UI components by extending base View classes and overriding their drawing, measurement, and layout methods. When combined with custom XML attributes, these components…
Dependency Injection is a design pattern where an object receives its dependencies from an external source rather than creating them internally. This inverts the control of object creation, moving it from the consuming…
Android's inter process communication (IPC) relies on the Parcel class as its low level transport container and the Parcelable interface as the contract that objects implement to serialize themselves into a Parcel.…
Jetpack Compose provides two state retention mechanisms that behave identically during normal recomposition but diverge when the system destroys and recreates the composable's host. remember keeps state alive across…
Kotlin sealed classes define a closed set of subtypes that are all known at compile time, enabling the compiler to verify that pattern matching covers every possible case. Unlike open classes where new subclasses can…
Android provides two mechanisms for converting objects into a transferable format: Java's Serializable interface and Android's Parcelable interface. Both enable passing objects between activities, fragments, and…
An Intent in Android is a messaging object that describes an operation to perform. It serves as the primary mechanism for communication between application components, whether those components live in the same process…
Jetpack Compose recomposes only the composable functions whose inputs have changed, but this optimization depends on the compiler's ability to determine whether inputs are stable. When the compiler cannot prove…
Kotlin data classes are a language feature that instructs the compiler to generate equals(), hashCode(), toString(), copy(), and componentN() functions based on the properties declared in the primary constructor.…
Kotlin delegated properties allow a class to hand off the getter and setter logic of a property to a separate delegate object using the by keyword. The compiler translates property access into calls on the delegate's…
Like what you see?
Subscribe to Dove Letter to get weekly insights about Android and Kotlin development, plus access to exclusive content and discussions.