Mobile App Development Interview Questions for 2 Years Experience
40 questions with answers for candidates with 2 years of experience — 8 easy, 28 medium, 4 hard.
What interviewers expect: 2 years experience
At two years, you should own features end to end. Expect deeper questions on Riverpod or Bloc, Redux or TanStack Query, authentication with token refresh, push notifications, platform permissions and writing tests. Scenario questions test how you handle offline use, slow networks and production bugs. Show that you think about edge cases and both platforms, not just Android or iOS.
This set is weighted towards Flutter State Management and Architecture (9), React Native Navigation, State and Native Modules (6), Mobile Development Fundamentals (5), Mobile Backend, APIs and Firebase (5).
Advanced state management Auth, tokens and push notifications Unit and widget or component tests Platform-specific setup
Solved at this levelStart practicing
3 QUESTIONS FREESign up to unlock the full question bank and track your progress.Unlock every question and answer, then continue practising company-wise and package-wise.
✓ 3 questions free • Unlock the rest in seconds
01
Write a Riverpod provider that fetches data asynchronously and display it in a widget.
Accessibility makes apps usable by people with disabilities. Provide labels for icons and images so screen readers like TalkBack and VoiceOver can announce them, keep touch targets at least 44 to 48 points, support dynamic text sizes, ensure colour contrast, and avoid conveying information only by colour. Flutter uses Semantics widgets, and React Native uses accessibilityLabel and accessibilityRole. Test with screen readers enabled.
Teams build custom REST or GraphQL APIs with Node.js, Java Spring Boot, Python or Go, hosted on cloud platforms. Backend-as-a-Service options like Firebase and Supabase provide authentication, databases, storage, functions and push notifications without managing servers, which suits startups and MVPs. Larger apps often combine a custom backend for business logic with managed services for auth, analytics and messaging.
04
Write a Dart HTTP client using dio with an interceptor that adds an auth token.
React.memo skips re-rendering a component when its props are shallowly equal. useCallback keeps the same function reference between renders, and useMemo caches a computed value, both only changing when dependencies change. They help when passing callbacks to memoised list items or computing expensive values. Overusing them adds complexity with little gain; the React Compiler can now apply such memoisation automatically in supported projects.
06
What security practices should every mobile app follow?
Use HTTPS everywhere and consider certificate pinning for high-risk apps. Store tokens only in secure storage, never log sensitive data, and keep secrets on the server. Obfuscate release builds, validate all input on the server, and protect sensitive screens from screenshots where needed. Check device integrity with platform attestation APIs for high-risk actions, and follow the OWASP Mobile Application Security Verification Standard as a checklist.
07
How do you implement OTP login with a phone number?
The user enters a phone number, the backend or an auth service sends an OTP via SMS and returns a verification ID. The user enters the code, which is verified to issue session tokens. On Android, use the SMS Retriever or User Consent API to auto-read the code without SMS permissions; on iOS, set the text content type to one-time code for autofill. Rate-limit requests, expire codes quickly and protect against abuse.
08
A Bloc emits the same state twice and the UI does not update. Why?
Bloc and Cubit skip emitting a state that is equal to the current one. If you mutate a list inside the existing state and emit the same object, equality holds and nothing rebuilds. Always emit a new state with copied collections, for example state.copyWith(items: [...state.items, newItem]), and implement equality with Equatable or freezed. Avoid mutable fields in state classes.
09
How do you make sure your code works before handing it to QA?
I test the happy path and edge cases myself on both Android and iOS, including no network, slow network, empty states, large text sizes and rotation. I write unit tests for logic and run the existing test suite. I review my own diff before raising the pull request and add clear testing notes for QA explaining what changed and what to check, which saves time for both of us.
10
Deep links open the app but land on the home screen instead of the product page. How do you debug it?
Check that the link configuration maps the URL path to the right screen name, including nested navigators, and that path parameters match. Verify verified link setup on both platforms: assetlinks.json for Android and the associated domains entitlement plus the site association file for iOS. Test with adb shell am start and xcrun simctl openurl. Also handle links when the app is cold started versus already running.
Isolates are Dart's units of concurrency, each with its own memory and event loop, communicating by messages. Heavy CPU work like parsing a large JSON file, image processing or encryption on the main isolate causes jank. Use Isolate.run or compute to run such work in a separate isolate and return the result. For network or file I/O, async-await is enough because that work is not CPU-bound.
12
Write a go_router configuration with an auth redirect.
Both platforms require runtime approval for sensitive features like camera, location, contacts and notifications. Android requires declarations in AndroidManifest.xml and runtime requests for dangerous permissions; iOS requires usage description strings in Info.plist, and the app crashes if a description is missing when requesting. iOS allows asking only once; later the user must change settings. Plugins like permission_handler or react-native-permissions unify the API.
14
What is app signing and why must you protect the keys?
Signing proves the app comes from you and that updates are from the same developer. On Android, you sign uploads with an upload key and Play App Signing re-signs with the app signing key held by the store; a lost upload key can be reset, but losing a self-managed app key meant you could never update the app. On iOS, signing uses certificates and provisioning profiles. Store keys in a secure vault and CI secrets, never in the repository.
Provider is simple and built on InheritedWidget but depends on BuildContext and can throw provider-not-found errors at runtime. Riverpod, from the same author, is compile-safe, independent of the widget tree, supports async providers and easy overrides for testing. Bloc uses events and states with streams, enforcing strict separation and traceability, popular in large teams and enterprises. Choose based on team familiarity and app complexity.
16
How do animations work in React Native and why use Reanimated?
The built-in Animated API can run animations on the native thread with useNativeDriver for transform and opacity, but not for layout properties. Reanimated runs animation logic in worklets on the UI thread, so animations stay smooth even if JavaScript is busy, and supports gestures, layout animations and shared element transitions. Combined with react-native-gesture-handler, it is the standard for complex interactive animations.
In Bloc, the UI adds events, the Bloc handles them with on<Event> handlers and emits new immutable states, and widgets rebuild with BlocBuilder or react with BlocListener. A Cubit is a simpler version where the UI calls methods directly and the Cubit emits states, without event classes. Use Cubit for straightforward logic and full Bloc when you need event transformations like debounce or detailed traceability.
18
Write a Flutter screen that fetches a list from an API using FutureBuilder.
Read the reviewer's message in App Store Connect carefully. Guideline 5.1.1 issues often involve requesting permissions without clear purpose strings, requiring sign-up for features that do not need an account, or missing account deletion. Fix the specific problem, for example improving usage description text or adding in-app account deletion, and reply in Resolution Center explaining the changes. Ask for clarification if the rejection is unclear.
20
Write a React Navigation setup with a stack containing a tab navigator and a details screen.
Firebase is a mobile and web development platform. Commonly used services are Authentication for email, phone OTP and social logins; Cloud Firestore and Realtime Database for synced data; Cloud Storage for files; Cloud Functions for server code; Cloud Messaging for push notifications; Crashlytics for crash reports; Analytics; Remote Config for feature flags; and App Distribution for testers. FlutterFire and React Native Firebase provide SDKs.
Deep links open a specific screen in your app from a URL. Custom schemes like myapp://order/42 work but are not verified. Verified HTTPS links are App Links on Android, using assetlinks.json, and Universal Links on iOS, using an apple-app-site-association file on your domain. When verified, the link opens your app directly instead of the browser. The routing library, like go_router or React Navigation linking, maps URLs to screens.
23
Write an EAS configuration for development, preview and production builds.
Agree on one approach with the team, for example Riverpod for app state and setState only for local widget state, and document examples. Migrate gradually, starting with the most buggy or most changed features, and write tests before moving logic. Add lint rules and pull request checklists so new code follows the standard. Avoid a big-bang rewrite that blocks feature work for weeks.
25
Store review is delaying your launch date. How do you plan releases to avoid this?
Submit builds early, a few days before the planned date, and use manual release so you can publish the approved build at launch time. Ship the code behind a remote feature flag so the feature can be enabled on launch day without a new review. Keep a pre-approved build ready, follow store guidelines closely and include clear review notes and demo login details for reviewers.
26
Explain the mobile app lifecycle states on Android and iOS.
Both platforms move apps between foreground active, inactive, background and terminated states. On iOS, an app goes inactive during interruptions like calls, then background, where it gets limited time before suspension. On Android, activities move through resumed, paused and stopped, and the process can be killed in background. Cross-platform apps observe these through AppLifecycleListener in Flutter or AppState in React Native to pause work and save data.
27
After an API call finishes, the app throws an error about using BuildContext across async gaps or setState after dispose. How do you fix it?
The user left the screen before the Future completed, so the widget was unmounted. Before using context or calling setState after await, check if (!context.mounted) return; or if (!mounted) return; in State. Better still, move async logic out of widgets into a state management layer that the UI listens to, and cancel subscriptions or timers in dispose so no callbacks run on a dead widget.
28
What is the difference between native, cross-platform and hybrid mobile apps?
Native apps are written in platform languages, Kotlin for Android and Swift for iOS, with full access to platform APIs and the best performance. Cross-platform frameworks like Flutter and React Native share one codebase and render native-feeling UI, saving time for two platforms. Hybrid apps, such as Ionic or Cordova, run web code inside a WebView. Choice depends on performance needs, team skills, budget and how much platform-specific UI is required.
useState stores local state and returns the value and a setter; calling the setter re-renders the component. useEffect runs side effects after render, like fetching data or subscribing to events, with a dependency array controlling when it re-runs, and a returned cleanup function to unsubscribe. Missing dependencies cause stale values, while unstable dependencies cause loops. For data fetching, libraries like TanStack Query are usually better than raw useEffect.
30
How do you implement authentication flow screens in React Navigation?
Conditionally render screen groups based on auth state: if the user is signed out, the navigator shows login and signup; when signed in, it shows the app screens. Changing state automatically switches stacks and prevents going back to login with the back button. Restore tokens from secure storage on startup while showing a splash screen. Expo Router offers protected routes for the same pattern.
31
The app needs a bottom navigation bar where each tab keeps its own navigation history. How do you implement it?
Use go_router's StatefulShellRoute.indexedStack, which creates a separate navigator branch for each tab and keeps their stacks alive with an IndexedStack. The scaffold shows a NavigationBar and switches branches with navigationShell.goBranch(index). This preserves scroll positions and nested pages when switching tabs, and deep links can open a specific tab and page. Handle tapping the active tab to pop to its root.
32
How do you secure Cloud Firestore data accessed directly from a mobile app?
Because the app talks to the database directly, security rules are the backend. Write rules that check request.auth for authentication and that users can read or write only their own documents, for example allow read, write: if request.auth.uid == userId. Validate fields and types in rules, never leave test mode rules open, and move sensitive operations like payments or role changes to Cloud Functions. Test rules with the emulator suite.
33
How do you handle error boundaries in a React Native app?
An error boundary is a class component, or a library like react-error-boundary, that catches rendering errors in its child tree and shows a fallback UI instead of crashing the whole app. Place one at the app root and around risky screens. They do not catch errors in event handlers or async code, so use try-catch there. Report caught errors to a crash reporting tool with context for debugging.
34
How do you explain your architecture choices to a new team member?
I start with the problem each layer solves, using one real feature from our app to trace a user tap through widget, state notifier, repository and API, and back to the UI. I share a short diagram and the team's architecture document, then give them a small task touching every layer. I review their first pull request closely and invite questions so they understand the reasons, not only the rules.
createState creates the State. initState runs once for setup like controllers and subscriptions; do not use inherited widgets there. didChangeDependencies runs after initState and when inherited data changes. build runs on every rebuild. didUpdateWidget runs when the parent rebuilds with new configuration. dispose runs when removed permanently, where you cancel streams, dispose controllers and timers to avoid memory leaks.
36
Write a React Native Testing Library test for a login button showing a validation error.
Rebuild only what depends on the changed data. Use selectors such as context.select, ref.watch(provider.select(...)) or BlocSelector to listen to one field, split big widgets into smaller ones, and use const constructors. Keep state objects immutable with proper equality so identical states do not trigger rebuilds. Use Flutter DevTools rebuild tracking to find widgets that rebuild more often than expected.
Since Dart 3, all code is null safe. Types are non-nullable by default, so String cannot hold null while String? can. The compiler forces you to handle nulls with checks, the ?. and ?? operators, or the ! operator which throws if null. The late keyword declares a non-null variable initialised later. Sound means the compiler can trust non-null types completely, enabling optimisations and preventing many runtime null errors.
39
Why use TanStack Query for server state in mobile apps?
Server state, such as data fetched from APIs, has caching, refetching, staleness and retry concerns that client state libraries do not handle well. TanStack Query caches responses by query keys, deduplicates requests, refetches on focus or reconnect, supports pagination and infinite queries, optimistic updates and offline persistence. It removes large amounts of useEffect and loading-state code and keeps screens consistent.
Maestro is an open-source mobile UI testing framework where flows are written in simple YAML, such as launchApp, tapOn "Login" and assertVisible "Welcome". It works with native, Flutter and React Native apps on Android and iOS, handles waiting automatically, and reduces flakiness compared to many older tools. Teams use it for smoke tests of critical journeys in CI because tests are quick to write and readable by QA.
Frequently asked questions
What is asked in Mobile App Development interviews for 2 years of experience?
At two years, you should own features end to end. Expect deeper questions on Riverpod or Bloc, Redux or TanStack Query, authentication with token refresh, push notifications, platform permissions and writing tests. Scenario questions test how you handle offline use, slow networks and production bugs. Show that you think about edge cases and both platforms, not just Android or iOS.
How many questions should I practise before a Mobile App Development interview?
Work through all 40 questions here, then the company-wise sets for the employers you are targeting. Quality matters more than count: be able to explain why each answer is right.
Which topics matter most for 2 years of experience?
Focus first on Advanced state management, Auth, tokens and push notifications, Unit and widget or component tests, Platform-specific setup.