Skip to content

Mobile Developer interview questions

100 real questions with model answers and explanations for Middle candidates.

See a Mobile Developer resume example

Practice with flashcards

Spaced repetition · Hunter Pass

Questions

uiuikitarchitecture-patterns

I keep the view model responsible for presentation state and user intents, not navigation, persistence, or platform UI objects.

  • The view renders immutable state and forwards events such as retryTapped or queryChanged.
  • Use cases own business decisions, while repositories hide network and database access.
  • A router or coordinator handles navigation so the view model can be tested without UIKit, SwiftUI, or Android navigation.

Why interviewers ask this: The interviewer is checking whether you can apply MVVM as boundaries rather than moving every responsibility into one large view model.

clean-architecturedependencies

Dependencies point toward stable business rules, so the domain layer does not import UI, database, or networking frameworks.

  • A domain use case depends on a repository interface, and the data layer implements that interface with Room, Core Data, or an HTTP client.
  • Framework models are mapped at the boundary instead of leaking Retrofit responses or NSManagedObject into the domain.
  • This costs mapping code, so I use the separation where business logic or data sources are likely to change, not for every trivial value.

Why interviewers ask this: A strong answer explains dependency direction and acknowledges the mapping cost instead of treating layers as folders.

repository-patternoop

The repository presents one domain-facing data contract and coordinates local and remote sources behind it.

  • Reads can observe the local database while a refresh updates that database from the API.
  • Writes are persisted locally with sync metadata, then queued for upload when connectivity permits.
  • The repository returns domain results and explicit freshness or sync status rather than exposing Room, Core Data, or transport DTOs.

Why interviewers ask this: The interviewer wants to see source coordination and a stable domain contract, not a repository that merely renames API calls.

I add a use case when an operation expresses reusable business behavior, but skip one-line pass-through wrappers.

  • Checkout can combine validation, inventory rules, and repository writes under one named operation.
  • The same use case can serve multiple screens and be tested without a UI framework.
  • If GetProfile only forwards repository.getProfile with no policy or composition, the extra type adds navigation overhead without a real boundary.

Why interviewers ask this: This tests whether you can distinguish a meaningful business boundary from architecture added only for pattern compliance.

resilience

I model one immutable screen state, reduce user actions into state changes, and isolate asynchronous work as effects.

  • The view emits actions such as Load and Retry but never mutates individual fields directly.
  • The reducer makes transitions explicit, for example Error to Loading to Content, which prevents contradictory flags.
  • Effects call repositories and feed results back as actions, so reducer tests stay deterministic and side-effect free.

Why interviewers ask this: The interviewer checks whether you understand reducers, effects, and impossible-state prevention beyond simply using a state container.

dependency-injection

A Hilt scope ties one instance to a generated component lifetime, so I choose it from the owner of the state.

  • SingletonComponent lives for the process and fits a database or configured HTTP client.
  • ActivityRetainedComponent survives configuration changes, while ViewModelComponent creates one instance per ViewModel.
  • Injecting a short-lived Activity into a singleton is invalid because the singleton could retain the destroyed Activity.

Why interviewers ask this: A strong answer connects Hilt components to Android lifecycles and recognizes lifetime inversion as a leak risk.

typesooptyping

I introduce an abstraction at a volatile boundary or test seam, not in front of every concrete class.

  • A PaymentAuthorizing interface isolates a vendor SDK whose API and testability are outside our control.
  • Constructor injection makes the required dependency visible and lets tests provide a small fake with deterministic results.
  • Pure value transformations can remain concrete because wrapping them in an interface adds indirection without substitutability value.

Why interviewers ask this: The interviewer is evaluating whether you use abstractions selectively and can explain the concrete testing or change benefit.

I split modules around cohesive features and stable shared capabilities, with small public APIs between them.

  • A checkout feature can expose its entry point and result types while keeping screens, reducers, and data mappings internal.
  • Core modules hold genuinely shared concerns such as networking or design tokens, not miscellaneous helpers.
  • Feature modules depend on domain contracts rather than each other's implementations, which limits rebuilds and accidental coupling.

Why interviewers ask this: The interviewer checks whether your modularization supports ownership and dependency control rather than producing arbitrary folders.

I keep domain models framework-free and map them explicitly at storage, network, and UI boundaries.

  • A nullable API field and a Core Data optional property can map into a domain type with a validated default or a failure.
  • Transport concerns such as snake_case keys and pagination envelopes stay in DTOs.
  • Platform display types such as UIImage, Bitmap, Color, or localized strings stay outside the domain model.

Why interviewers ask this: This tests whether you can preserve a stable domain language while handling imperfect external schemas.

I expose a narrow capability API with platform-neutral inputs, outputs, and lifecycle rules.

  • The module accepts identifiers and value objects rather than UIViewController, Activity, or framework-specific state types.
  • Native adapters translate callbacks or async results into Swift, Kotlin, React Native, or Flutter conventions.
  • Versioned contracts and contract tests keep bridge changes from silently breaking one platform while another still compiles.

Why interviewers ask this: The interviewer is looking for boundary design that survives multiple UI stacks without leaking one framework across the module.

asyncconcurrencyswift

I use async let for a fixed small set of child operations and a task group for a dynamic collection.

  • async let starts child work immediately and awaits typed results within the current scope.
  • withThrowingTaskGroup can add one child per item and consume results as they finish.
  • Both preserve structured concurrency, so leaving the scope waits for or cancels its children instead of orphaning work.

Why interviewers ask this: The interviewer checks whether you understand structured task lifetime, not only async and await syntax.

asyncswiftconcurrency

Swift task cancellation is cooperative, so cancellation sets a flag and participating code must stop promptly.

  • Task.checkCancellation throws at a useful boundary, while Task.isCancelled supports cleanup before returning.
  • Suspending APIs such as Task.sleep react to cancellation, but CPU loops need their own periodic checks.
  • A cancellation handler can release resources, but cleanup must stay safe if the operation already partially completed.

Why interviewers ask this: A strong answer knows that calling cancel does not forcibly terminate arbitrary work and explains where checks belong.

asyncconcurrency

An actor protects isolated state from simultaneous access, but another task may enter the actor while the first method is suspended.

  • State read before an await may be stale when execution resumes.
  • I capture only immutable inputs before suspension and revalidate actor state after the awaited call.
  • For a balance update, I avoid a read, await, write sequence unless the final write checks the current balance again.

Why interviewers ask this: The interviewer is testing whether you understand actor reentrancy rather than assuming an entire async method is atomic.

concurrencyswiftcommunication

Sendable marks values that can safely cross concurrency domains without introducing shared mutable state.

  • Immutable value types usually satisfy it naturally when all stored properties are also Sendable.
  • A mutable reference type needs synchronization, actor isolation, or a redesign before it can honestly conform.
  • unchecked Sendable suppresses compiler proof, so I reserve it for types whose thread safety is enforced and documented elsewhere.

Why interviewers ask this: The interviewer checks whether you treat Sendable as a safety contract rather than an annotation used to silence warnings.

I isolate UI state and UI mutations to MainActor, then keep network and CPU-heavy work outside that isolation.

  • Marking a view model MainActor makes its published state mutations compiler-checked.
  • An async network call can suspend without blocking the actor, but synchronous image processing on it would still freeze UI work.
  • I move parsing into a non-MainActor async service with Sendable input and output; I use Task.detached only for justified unstructured CPU work, capture only Sendable values, and propagate cancellation.

Why interviewers ask this: A strong answer distinguishes actor isolation from background execution and avoids doing heavy synchronous work on the UI actor.

concurrencycoroutineskotlin

Structured concurrency makes child coroutine lifetimes and failures belong to an explicit parent scope.

  • coroutineScope waits for all children and cancels siblings when one child fails.
  • supervisorScope isolates child failures when independent work should continue.
  • I launch UI work in viewModelScope rather than GlobalScope so clearing the ViewModel cancels outstanding jobs.

Why interviewers ask this: The interviewer wants lifecycle and failure semantics, not just knowledge of launch and async.

coroutines

I choose a dispatcher for the kind of work and switch only at the boundary that owns that work.

  • Dispatchers.Main handles UI state, Dispatchers.IO fits blocking file or legacy database calls, and Default fits CPU-bound transformations.
  • A repository can use withContext for a blocking dependency so callers do not need to know its execution requirement.
  • I do not wrap naturally suspending Retrofit or Room calls in IO because those APIs already avoid blocking the caller thread.

Why interviewers ask this: A strong answer assigns dispatchers by workload and avoids redundant or caller-controlled switching.

coroutineskotlinresilience

I let CancellationException propagate and make long-running custom work check cancellation cooperatively.

  • Suspending functions normally check cancellation, while a CPU loop should call ensureActive or yield periodically.
  • A broad catch of Exception must rethrow CancellationException or it can keep dead UI work alive.
  • Cleanup belongs in finally, with NonCancellable used only for a short mandatory suspend such as closing a transaction.

Why interviewers ask this: The interviewer checks whether error handling preserves coroutine cancellation and lifecycle ownership.

coroutines

A regular Flow is usually cold and starts work per collector, while StateFlow is hot and always exposes a current value.

  • I use a cold Flow for a query or stream whose producer should start when collected.
  • A ViewModel exposes StateFlow for screen state because a recreated collector immediately receives the latest value.
  • stateIn with a lifecycle-aware sharing policy converts an upstream Flow without keeping expensive work active forever.

Why interviewers ask this: The interviewer is evaluating stream lifetime, replay behavior, and state ownership rather than API memorization.

combine

Combine subscribers request demand, and the subscription stays active only while its cancellation token is retained.

  • Operators propagate demand upstream, although some publishers can buffer or produce faster than downstream consumes.
  • sink returns an AnyCancellable that I store with the owner and release when that owner should stop observing.
  • Closures should capture self weakly when the owner retains the cancellable, otherwise the subscription chain can form a cycle.

Why interviewers ask this: A strong answer covers both backpressure semantics and the common AnyCancellable ownership cycle.

Locked questions

  • 21

    How do you decide who owns state in SwiftUI?

    swiftuiswift
  • 22

    How would you design conflict resolution for a CloudKit record edited on multiple devices?

    conflictdesign
  • 23

    How would you design a type-safe boundary between React Native TypeScript and native code?

    reactdesigntypescript
  • 24

    How do you hoist state in Jetpack Compose without making the screen API unwieldy?

    composeapijetpack
  • 25

    How would you design navigation so it is testable across declarative mobile UIs?

    navigationdesign
  • 26

    For a new checkout feature, how would you choose between VIPER, MVVM, and Clean Architecture boundaries?

    architecture-patternsclean-architecture
  • 27

    How do you embed UIKit inside SwiftUI without creating update loops or duplicate ownership?

    uikitswiftuiownership
  • 28

    What changes with React Native's New Architecture, and how do Hermes, Fabric, and TurboModules fit?

    reactarchitecture
  • 29

    How do Widget, Element, and RenderObject differ in Flutter?

    flutterwidgetscustom-rendering
  • 30

    How would you design a Flutter platform-channel integration for a native capability?

    flutterdesign
  • 31

    How do you expose an Objective-C framework safely to Swift?

    swift
  • 32

    How do you structure Core Data contexts for responsive reads and safe background writes?

    responsiveandroid-componentsswift
  • 33

    How do you plan schema migrations for Room and Core Data?

    schemamigrationsroom
  • 34

    What should a mobile cache policy define beyond a time-to-live?

    caching
  • 35

    How would you model a durable sync queue for offline mutations?

    data-structures
  • 36

    Why must offline sync operations be idempotent?

    idempotency
  • 37

    How do you choose a conflict-resolution strategy for offline edits?

  • 38

    What guarantees and constraints should you design around when using WorkManager?

    designjetpackautolayout
  • 39

    What limitations shape the design of iOS background work with BGTaskScheduler?

    design
  • 40

    How do tombstones help synchronize offline deletions?

  • 41

    How should a mobile app manage the OAuth access-token and refresh-token lifecycle?

    oauthtokenslifecycle
  • 42

    How would you use Keychain, Android Keystore, and CryptoKit for locally protected secrets?

    secretssecure-storage
  • 43

    What are the trade-offs of certificate pinning in a mobile app?

  • 44

    What does biometric authentication actually prove to an application?

    auth
  • 45

    How do you design mobile data collection for privacy rather than only asking for permission?

    designpermissions
  • 46

    How do you validate a deep link before navigating to protected content?

    validationnavigation
  • 47

    How should an application handle the push-notification token lifecycle?

    lifecycleandroid-componentstokens
  • 48

    How do you manage camera and sensor resource ownership across mobile lifecycles?

    ownershiplifecycle
  • 49

    How do you design a reliable mobile purchase flow?

    design
  • 50

    How do you keep a normalized GraphQL mobile cache consistent after mutations and pagination?

    graphqlpaginationnormalization
  • 51

    On iOS, a cold deep link to order 42 opens correctly, but then a restored NavigationStack path replaces it with the screen from the previous session. How would you fix the launch race?

    navigationsessions
  • 52

    A Jetpack Compose screen recomposes about 120 times per second while a timer runs, dropping scrolling to 40 fps. How would you isolate and stop the recomposition storm?

    composeconcurrencyjetpack
  • 53

    A StoreKit 2 purchase succeeds, but the app is terminated before the backend grants premium access; after relaunch the user remains locked and the transaction is unfinished. How would you recover safely?

    transactions
  • 54

    A long-lived Jetpack Compose effect submits the item that was selected when the screen first opened, not the current item. How would you diagnose and fix the stale lambda?

    composelambdajetpack
  • 55

    Opening and closing a screen ten times leaves ten network polls running and adds 30 MB of retained memory. How would you find and fix the coroutine leak?

    memorycoroutines
  • 56

    A Swift concurrency refactor makes a search screen freeze for 900 ms because parsing now runs through a main-actor-isolated view model. How would you correct the actor boundary?

    concurrencyswiftui
  • 57

    Every visit to an iOS profile screen adds one active Combine subscriber, and deinit is never called after 20 visits. How would you locate and remove the subscription leak?

    combine
  • 58

    A React Native chart receives an 18 MB JSON payload across the JS/native boundary every 200 ms and the UI falls to 25 fps. What would you change?

    react
  • 59

    Typing into one Flutter form field rebuilds an entire tab of 300 widgets and produces visible frame misses. How would you reduce the rebuild scope?

    formsflutterwidgets
  • 60

    A Flutter plugin works in debug but Android release builds throw MissingPluginException on one method, while iOS works. How would you debug the platform channel failure?

    flutterplatform
  • 61

    An offline queue replays after an app restart and creates duplicate expense records in 1.8% of syncs. How would you make the write path safe?

    data-structures
  • 62

    Two devices edit the same offline note, then reconnect and silently overwrite each other. How would you implement and test conflict handling?

  • 63

    An Android update jumps a Room database from version 8 to 10 and crashes only users who skipped version 9. How would you fix and prevent this migration gap?

    databasemigrationsroom
  • 64

    A Core Data model update causes a 0.7% launch crash on stores created three releases ago, and lightweight migration cannot infer the mapping. What is your recovery plan?

    migrationsmodelingcore-data
  • 65

    A non-atomic CloudKit batch saves 30 tasks; one item returns CKError.serverRecordChanged inside partialFailure, but the app retries all 30 and overwrites a collaborator's title. How would you repair the sync?

    batchconcurrency
  • 66

    Changing a search filter during infinite scroll sometimes appends an old page, creating duplicate rows and a wrong next cursor. How would you eliminate the pagination race?

    deduppagination
  • 67

    A 200 MB upload reaches 70%, the OS kills the background job, and the app restarts from zero each time. How would you make progress durable?

    jobs
  • 68

    Some users receive the same order push twice from FCM and see two notifications. How would you deduplicate without dropping a legitimate update?

    queriesandroid-components
  • 69

    A protected deep link opened from a cold start is lost after login, while a crafted link can reach an internal admin route. How would you fix both issues?

    navigation
  • 70

    Taking five 12 MP photos grows memory by about 240 MB and crashes low-memory devices. How would you diagnose and fix the camera pipeline?

    memoryci-cd
  • 71

    Production cold start p95 is 3.2 seconds, while warm start is 600 ms. How would you find and remove the cold-only work?

  • 72

    A feed reports 22% slow frames when users fling through 1,000 mixed-content rows. How would you reduce list jank?

    rendering
  • 73

    A Codegen TurboModule streams camera frames to React Native; after opening and closing the analyzer 20 times, RSS grows by 15 MB per cycle while the Hermes heap returns to baseline. How would you find and fix the leak?

    data-structuresstreamsreact
  • 74

    Play Console shows a six-second ANR during app resume, with the main thread inside a Room query and JSON decode. How would you resolve it?

    queriesroomconcurrency
  • 75

    The app consumes 12% battery per hour while idle after enabling live location. How would you identify and stop the drain?

  • 76

    During a backend outage, each device sends about 30 retries per second and makes recovery slower. How would you stop the network retry storm?

    resilience
  • 77

    After three background and foreground cycles, one device holds four WebSocket connections and receives every message four times. How would you fix the lifecycle?

    websocketslifecycle
  • 78

    Parsing a 25 MB JSON response takes 1.4 seconds and temporarily doubles app memory. How would you reduce the cost?

    memory
  • 79

    Local search over 100,000 records takes 600 ms and blocks each keystroke. How would you optimize the database query?

    databasequeriesoptimization
  • 80

    A newly added analytics SDK adds 800 ms to cold start and raises crashes from 0.2% to 0.5%. How would you contain the integration?

  • 81

    A pricing feature has 85% line coverage but still ships rounding and stale-state regressions. How would you redesign the unit-test strategy?

    coveragetest-strategyhypothesis-testing
  • 82

    Seven recent bugs occurred between the API cache and Room database even though repositories are heavily mocked in unit tests. What integration tests would you add?

    unitintegrationintegration-testing
  • 83

    The mobile E2E suite takes 48 minutes, fails 14% of runs, and blocks releases. How would you reshape it without losing checkout coverage?

    e2ecoverage
  • 84

    An asynchronous view-model test fails about once in 20 runs because it sleeps 500 ms before asserting. How would you make it deterministic?

    asyncconcurrencyui
  • 85

    A release passes on current flagship phones but crashes on Android 10 low-memory devices and lays out incorrectly on iPhone SE. How would you define the device matrix?

    memory
  • 86

    The backend changes a nullable field to missing and older app versions crash during decoding. How would contract tests prevent this class of release?

    contract
  • 87

    iOS CI archives fail on clean runners because the signing profile expires next week and developers rely on local Keychain state. How would you stabilize signing?

    secure-storage
  • 88

    A Fastlane release uploaded the staging flavor to production with the wrong bundle ID and screenshots. How would you prevent a repeat?

  • 89

    During a staged release, crash rate rises from 0.2% to 1.1% at 10% rollout. What actions and gates would you use?

  • 90

    A clean mobile build takes 22 minutes, warm builds vary from 4 to 15 minutes, and the cache hit rate is only 35%. How would you improve build performance?

    caching
  • 91

    A Bitrise workflow exposes an App Store Connect key and signing password to pull-request builds, where a third-party step can read the environment. How would you contain the incident and isolate signing?

    incidentspasswordsdependencies
  • 92

    When 20 requests receive 401 together, the app launches 20 token refreshes, overwrites newer tokens, and sometimes logs the user out. How would you fix the refresh race?

    tokens
  • 93

    After a server certificate renewal, TLS starts failing only on Android API 24-25 because the server omits an intermediate certificate. How would you diagnose and fix it?

    tlsapi
  • 94

    After a Face ID enrollment change, paying users are permanently locked out because the biometric key is invalidated and no fallback appears. How would you repair the flow?

  • 95

    A payment timeout followed by a retry causes double charges in 0.15% of purchases. How would you make the mobile flow idempotent?

    resilienceidempotency
  • 96

    Only 38% of users grant camera access, and review flags the permission text because it says features require the camera without naming the use. How would you improve the flow?

    permissions
  • 97

    VoiceOver and TalkBack skip the order total, read three unlabeled buttons as button, and focus jumps after validation. How would you fix and verify the screen?

    validation
  • 98

    A new checkout behind a feature flag raises crashes from 0.2% to 2%, but some offline users keep the cached enabled value after rollback. How would you design a safer kill switch?

    feature-flagsrollbackdesign
  • 99

    In code review, a PR stores an Activity in a singleton to launch a payment SDK, and LeakCanary shows one retained Activity per checkout. How would you handle the review?

    code-reviewandroid-components
  • 100

    A junior's push parser uses forced casts and causes 0.4% of launches from notifications to crash on an optional field. How would you mentor them through the fix?

    mentoringandroid-componentsswift