Interview questions · free
Flutter Developer interview questions and answers
27 questions Flutter Developer interviews in India ask, grouped by the 6 skills they test, with a short model answer for each. Then the HR round every job has. Try each one out loud before you open the answer.
- 27 questions
- 6 skills
- 13 for freshers
- Updated 30 Oct 2026
First mock interview free: 3 questions, a score and feedback on each · No card needed
Answer out loud first. Read the question, say your answer as you would in the room, then open the model answer and compare. Interviewers ask follow-ups, so learn the reasoning, not the words.
Mobile platform · Core skill
UI and layouts
In Flutter everything on screen is a widget, so interviewers spend most of the technical round on how widgets build, lay out and rebuild, and on keeping scrolling smooth.
What is the difference between a StatelessWidget and a StatefulWidget? What does setState actually do?Fresher
A StatelessWidget has no data of its own that changes: it builds its UI only from the values passed to it, like a label or an icon. A StatefulWidget has a separate State object that keeps data across rebuilds, like a counter, a form field's text or an animation controller.
Calling setState tells Flutter that this State's data has changed, so it marks the widget as dirty and calls build again on the next frame. It doesn't redraw the whole app, only that widget's subtree. Change the data inside the setState callback, keep build fast and free of side effects, and never call setState after the widget is disposed: check mounted after an await.
You put a ListView inside a Column and get an error about unbounded height, or you see a yellow-and-black overflow stripe. Why, and how do you fix it?Fresher
Flutter's layout rule is that constraints go down, sizes go up, and the parent sets the position. A Column gives its children unlimited height, but a ListView wants to be as tall as its constraint allows, so it can't decide its size and throws the unbounded height error. Wrap it in Expanded or Flexible so it takes the remaining space, or give it a fixed height with a SizedBox.
The overflow stripe means children are bigger than the space the parent has, like a Row of long text on a narrow phone. Fix it with Expanded or Flexible, text overflow and wrapping, or a scroll view. Avoid shrinkWrap: true on long lists, because it builds every item.
How would you make a Flutter screen work on small phones, tablets and the web?Fresher
Base the layout on the space actually available, not on one device. LayoutBuilder gives the parent's constraints, so I can switch at breakpoints: one column below about 600 logical pixels, and a list with a detail pane, or a grid with more columns, above that. MediaQuery gives the screen size, padding and the user's text scale, and SafeArea keeps content clear of notches and system bars.
Inside a layout I use Expanded, Flexible, Wrap and scroll views instead of fixed widths, so text can grow with larger font settings. I test in the emulator at different sizes, in landscape, with a large text scale, and in a resizable browser window if the app also runs on the web.
What are keys in Flutter, and when do you need them?1-6 years
A key tells Flutter which widget is which when the widget tree changes. Flutter keeps a tree of elements behind your widgets and, on a rebuild, matches old and new widgets by type and position. Usually that's fine, but when items of the same type are reordered, inserted or removed, such as in a list of stateful todo items, Flutter can attach the old state to the wrong item: the wrong checkbox stays ticked.
Giving each item a ValueKey with its ID fixes it, because matching then uses the key. Use ValueKey or ObjectKey in lists, PageStorageKey to keep a list's scroll position, and GlobalKey only when you really need access to a widget's state from elsewhere, such as a Form, since it's costly.
A Flutter screen with a long list of images drops frames while scrolling. How do you find and fix the problem?1-6 years
I profile in profile mode on a real, preferably low-end device, never in debug mode, which is much slower. Flutter DevTools shows each frame's time on the UI thread, which runs your build and layout code, and the raster thread, which draws. A slow UI thread points to heavy build methods or too many rebuilds; a slow raster thread points to expensive drawing such as large images, opacity and clipping.
Typical fixes: use ListView.builder so only visible items are built, mark unchanging widgets const, move work like parsing or sorting out of build, rebuild only the part of the screen that changes, and decode images at display size with cacheWidth or a caching image package, instead of full-resolution photos.
Language · Core skill
Kotlin / Swift / Dart
Flutter is written in Dart, and interviewers expect you to know its null safety, async model and object features, because they shape how every widget and service is written.
What is the difference between final and const in Dart? Why do Flutter developers use const so much?Fresher
Both mean the variable can't be reassigned. A final value is set once, at runtime, so final now = DateTime.now() is fine. A const value must be known at compile time, and it's deeply immutable: a const list can't be changed at all. Identical const values are created only once and shared.
In Flutter that matters because a const widget, such as const Text('Hello') or const SizedBox(height: 8), is the same instance on every rebuild, so Flutter can skip rebuilding it. Using const constructors wherever possible is a cheap performance win, and the linter can suggest them. A widget can only be const if all its arguments are const too.
Explain null safety in Dart. What do ?, !, ?? and late mean?Fresher
With sound null safety, a variable can't be null unless its type says so: String name can never be null, String? name can. The compiler makes you handle null before using a nullable value. name?.length returns null instead of crashing if name is null. name ?? 'Guest' gives a default, and name ??= 'Guest' assigns one only if it's null. name! tells the compiler you're sure it isn't null, and throws at runtime if you're wrong.
late means a non-nullable variable will be set before it's used, for example in initState; reading it earlier throws an error. Use required for named parameters that must be passed. Prefer ?? and checks over !, which hides bugs.
What is the difference between a Future and a Stream in Dart? Give a Flutter example of each.Fresher
A Future is a single value that arrives later, or an error: an HTTP request returning one response, or reading a file. You wait for it with await inside an async function, or show it with FutureBuilder. A Stream is a sequence of values over time: location updates, a chat's new messages, or a Firestore query that changes. You listen to it, or use await for, or show it with StreamBuilder.
Common mistakes: creating the Future inside build, so FutureBuilder restarts the request on every rebuild (create it once, in initState or a state class), and forgetting to cancel a stream subscription in dispose, which leaks memory and calls setState on a disposed widget.
Dart is single-threaded. How does it run async code without freezing the UI, and when do you need an isolate?1-6 years
Each isolate runs one event loop with a microtask queue and an event queue. When you await a network call, the request is handled by the platform, and Dart keeps processing other events, such as taps and frames, until the result arrives and the rest of your function is queued. So waiting is fine; it's long CPU work on the main isolate that freezes the UI, because nothing else can run until it finishes.
For heavy computation, like parsing a very large JSON response, image processing or encryption, run it in another isolate with Isolate.run or Flutter's compute. Isolates don't share memory; they pass messages, so data is copied between them. Use them only when profiling shows dropped frames.
How do you write a model class in Dart with value equality, copyWith and JSON parsing? Do you write it by hand?1-6 years
Dart has no built-in data classes, so by default two objects with the same fields aren't equal. By hand, you override == and hashCode, add a copyWith method that returns a new object with some fields changed, and write a fromJson factory and a toJson method. That's a lot of code to keep correct when fields change, so most teams generate it: json_serializable for JSON, and freezed for equality, copyWith, toString and union types, using build_runner.
Equatable is a lighter option for equality alone, popular with Bloc states. Keep models immutable with final fields. Dart 3's records and sealed classes also help, for example a sealed result type that's either success or failure.
App architecture
Architecture patterns
State management is the most debated topic in Flutter, so interviewers ask what you've used, why, and how you'd structure an app that a team can keep growing.
When is setState enough, and when do you need a state management solution like Provider, Riverpod or Bloc?Fresher
setState is enough for state that belongs to one widget, like whether a password is visible or the current tab. The trouble starts when several screens need the same data, such as the logged-in user or a cart: passing it down through constructors gets messy, and business logic ends up inside widgets.
State management solutions keep that state outside the UI and let any widget below read it and rebuild when it changes. Provider wraps Flutter's InheritedWidget and is simple; Riverpod is its successor, compile-safe and not tied to the widget tree; Bloc uses events and states with streams and suits large teams. Say which you've used, and that consistency within one project matters more than the choice.
Explain the Bloc pattern. How is a Cubit different from a Bloc?1-6 years
Bloc separates business logic from the UI. The UI sends events, such as LoginSubmitted, the Bloc handles them, calls repositories, and emits new states, such as LoginLoading, LoginSuccess or LoginFailure, which the UI rebuilds from with BlocBuilder. BlocListener is for one-time reactions like navigation or a snackbar, and BlocConsumer does both.
A Cubit is the simpler form: instead of events, the UI calls methods on it directly, like cubit.login(email, password), and it emits states. Use a Cubit for straightforward screens; use a full Bloc when you need event transformations, such as debouncing a search field, or a clear log of every event. Both are easy to unit test with the bloc_test package.
How would you structure the folders and layers of a large Flutter app?1-6 years
I organise by feature first, such as auth, products and cart, each with its own layers, rather than one huge widgets folder and one huge models folder. Within a feature, the presentation layer has screens, widgets and the state classes; the domain layer has entities and use cases with the business rules; the data layer has repositories, API clients and local storage. Widgets never call the API directly.
Dependencies point inwards and are injected, with Riverpod providers or get_it, so the data source can be swapped for a fake in tests. Shared code like theming and networking goes in a core folder, and very large apps split features into separate Dart packages. Keep it lighter for small apps; layers have a cost.
Networking
APIs and networking
Most Flutter apps are front ends for a backend, so expect questions on calling APIs with http or Dio, parsing JSON into models and handling tokens and errors.
How do you call a REST API in Flutter and turn the JSON into a Dart object?Fresher
With the http package: final res = await http.get(Uri.parse(url)); check res.statusCode, then jsonDecode(res.body) gives a Map, which a factory constructor such as User.fromJson turns into a typed object. For a list, map each element through fromJson. Dio is a popular alternative with interceptors, timeouts, cancellation and automatic JSON decoding built in.
Keep API calls in a repository or service class, not inside widgets, and call them from your state management layer. Mention that very large responses can be parsed in a background isolate with compute so the UI doesn't stutter, and that code generation with json_serializable avoids typing mistakes in fromJson.
Using Dio, how would you attach an access token to every request and refresh it when it expires?1-6 years
I add an interceptor. In onRequest it reads the access token from secure storage and sets the Authorization header. In onError, if the response is 401, it calls the refresh endpoint, saves the new tokens and retries the original request with the new token, then resolves the handler with that response. If refreshing fails, it clears the tokens and sends the user to the login screen.
Two details matter. If several requests fail together, only one refresh should run while the others wait, so I use a lock or a QueuedInterceptor. And the refresh call must use a separate Dio instance without this interceptor, or a failed refresh loops. Tokens go in flutter_secure_storage, not shared_preferences.
How do you handle network errors in a Flutter app, including no internet, timeouts and server errors?1-6 years
I convert every failure into something the UI can show. With Dio, a DioException has a type: connection or receive timeouts, connection errors when there's no network, and bad responses with a status code I map to a message, such as 404 not found or 500 server problem. JSON that doesn't match the model raises a parsing error, which I catch and log. The repository returns a result type, success or failure, and the state layer turns it into an error state with a retry button.
The connectivity_plus package only says whether Wi-Fi or mobile data is on, not whether the internet actually works, so handle the real request failure anyway. Set timeouts, and don't retry non-idempotent requests like payments automatically.
Reading an answer isn't the same as giving one
In a mock interview you answer new Flutter Developer questions out loud or typed, and every answer is scored, with what to fix and a stronger answer.
Mobile platform
Local storage
Users expect apps to remember them and work on patchy networks, so interviewers ask which Flutter storage package you'd choose and how you cache data.
Which ways of storing data locally in Flutter do you know, and when would you use each?Fresher
shared_preferences stores small key-value settings, like dark mode or whether onboarding was seen. It isn't encrypted, so tokens and personal data belong in flutter_secure_storage, which uses the Android Keystore and the iOS Keychain. Structured data you query, like orders or cached products, belongs in a database: sqflite for plain SQLite, or Drift, which adds type-safe queries, streams and migrations on top of SQLite. Files such as downloads or exports go in the app's documents or temporary directory from path_provider.
NoSQL packages like Hive are also used. Before choosing any package, check it's actively maintained and supports the platforms you target, including the web if needed.
Your released app uses sqflite, and the next version needs a new column. How do you handle the database upgrade?1-6 years
I increase the database version in openDatabase and handle it in onUpgrade, which receives the old and new versions. For each step I run the change, such as ALTER TABLE orders ADD COLUMN status TEXT DEFAULT 'pending', checking the old version so a user jumping from version 1 to 3 runs every step in order. onCreate must create the latest schema for new installs.
I test the upgrade by installing the old release, adding data, and updating to the new build, because a failed migration crashes on launch or loses users' data. Drift has built-in migration tools and schema tests, one reason teams prefer it. Never delete and recreate a table just to change it, unless the data is only a cache.
How would you show data instantly when the app opens, even offline, and still keep it fresh?1-6 years
I use the cache-then-network approach with the local database as the source the UI reads. On opening, the repository returns what's stored, so the screen fills at once, even offline. It then fetches from the API in the background, writes the new data to the database, and the UI updates through a stream, for example a Drift watch query or a Bloc emitting a new state. If the fetch fails, the user keeps the cached data with a small message.
I store a fetched-at time and refresh only when the data is older than a set limit. Images are cached on disk with a package such as cached_network_image. Mention how you'd clear the cache on logout so the next user doesn't see it.
Quality
Testing
Flutter has unit, widget and integration tests built in, and interviewers check that you know which to write and how to keep tests fast and reliable.
What are unit tests, widget tests and integration tests in Flutter?Fresher
A unit test checks one function or class, such as a validator or a repository with a fake API, using the test function; it's very fast. A widget test builds one widget or screen in a test environment without a device: testWidgets, then tester.pumpWidget, find a widget with finders like find.text, tap it, and check the result with expect. It's still fast and catches most UI bugs.
An integration test runs the whole app on an emulator or real device with the integration_test package, for example logging in and placing an order. It's slow, so keep only a few for the most important flows. Most of your tests should be unit and widget tests, run in CI on every change.
How do you test a Bloc or a widget that depends on an API, without calling the real server?1-6 years
Depend on an abstract repository rather than the HTTP client, and inject it, so in tests you can pass a mock. With mocktail or mockito, I stub the method, for example when(() => repo.fetchProducts()).thenAnswer((_) async => products), or make it throw to test the error path. For a Bloc, the bloc_test package's blocTest takes the build function, the act and the expected list of states, such as loading then loaded.
For a widget test, I wrap the screen in its providers with the mocked repository, pump it, and check what's shown for each state. Verify that the repository was called the expected number of times, and test failure cases, not only the happy path.
Your widget test hangs or times out at pumpAndSettle. Why, and what is the difference between pump and pumpAndSettle?1-6 years
pump draws one frame, optionally after advancing time by a duration. pumpAndSettle keeps pumping frames until nothing more is scheduled, which suits waiting for a page transition or a short animation to end. If something animates forever, like a CircularProgressIndicator shown while loading, there's always another frame scheduled, so pumpAndSettle never settles and times out.
The fix is to make sure the loading finishes, by having the mocked repository return immediately, or to use pump with a duration and check the loading state directly. For visual checks, golden tests compare a widget's rendering with a saved image. On real devices, run integration tests on a few Android and iOS phones, for example in Firebase Test Lab.
Every job
HR and behavioural round
Flutter roles are often in startups and service companies building for clients, so the HR round checks how you handle deadlines, both app stores and learning native code when needed.
Walk me through a Flutter app you've built. What did you do yourself?Fresher
Pick your strongest app and tell it as a short story: the problem, what you built, the hardest part and the result. For example: "I built [app], which helps [users] to [task]. I wrote the UI and state management with [Riverpod / Bloc], connected it to [Firebase / a REST API], and stored data offline with [package]. The hardest part was [problem, for example images making the list lag], which I fixed by [solution]. [Number] people use it, or it's on the Play Store."
Be clear about which parts you wrote and which came from a tutorial or a teammate. Have it on your phone to demonstrate.
Why Flutter? What would you say to a client who asks whether they should build native apps instead?Fresher
Give a balanced answer, which shows maturity. Flutter's strengths: one Dart codebase for Android and iOS, and often web, so a small team ships faster; hot reload; and a consistent UI across devices. Its trade-offs: a larger app size than a minimal native app, some platform features need platform channels or native code, and very platform-specific apps, like ones built around new OS features, may suit native better.
For example: "For a shopping or booking app on a tight budget, Flutter is a strong choice. If the app depends on [deep hardware or OS features], I'd check plugin support first, or recommend native." That honesty builds trust.
Tell me about a problem that appeared only on iOS or only on Android. How did you solve it?1-6 years
Use STAR and show how you debugged across platforms. "Our app worked on Android, but on iOS the camera screen crashed (situation). I owned that feature (task). I reproduced it on a real iPhone, read the Xcode logs, and found the camera usage description was missing from Info.plist, which iOS requires before asking for permission (action). I added it, documented the setup for both platforms, and added a release checklist item; the build passed App Store review (result)."
Other good examples are keyboard behaviour, permissions, notch handling and store review rejections. Show that you're not afraid to open the native Android or iOS project.
If the project needs a native Android or iOS module, or a different framework, would you be willing to learn it?Fresher
Say yes and give evidence that you learn quickly, without sounding as if Flutter was a passing interest. For example: "Yes. Flutter apps sometimes need native code, through platform channels, for features without a plugin, so knowing some Kotlin and Swift makes me a better Flutter developer. In my project I [wrote a small platform channel / read native plugin code] to [do something]. I'd learn what the project needs, and I'm comfortable reading documentation and asking teammates."
Interviewers at service companies ask this because project needs change; a flexible answer helps.
A client wants a new feature by Friday, but you estimate it needs two weeks. What do you do?1-6 years
Raise it early and offer options, rather than silently working late or missing the date. Break the feature down to show where the time goes, then propose choices: a smaller first version by Friday, more people, or moving another task. For example: "I explained that offline sync alone needed a week. We shipped the screens with online-only data on Friday and added offline support the following sprint. The client could demo on time, and nothing was rushed."
Show that you protect quality, such as testing and store review time, and keep your manager informed before you speak to the client, if that's the team's process.
Free interview questions, roadmaps and mock interviews: https://myskillgrid.com/interview-questions/flutter-developer/
Ready to answer them for real?
Your first Flutter Developer mock interview is free: 3 questions, a score and feedback for each, and a stronger answer to learn from, in about 10 minutes.