Skip to content
tezvyn:

Top 30 Easy Flutter & Dart Interview Questions and Answers for Freshers

30 easy multiple-choice Flutter & Dart interview questions, the ones an interviewer opens with: definitions, everyday syntax, and the quick checks that you have really used it. They come from 30 bites in the Flutter & Dart library, the gentlest slice of the 138 Flutter & Dart interview questions in the library. Answer them here or read straight down. Every question carries the correct option, why it is correct, and a link to the bite it came from.

Flutter framework, Dart language, packages, Impeller

30 questions. Pick an answer, or open “Show the answer” to read it.

Answers are graded in your browser. Nothing is saved, and no XP or streak is earned here. The app keeps score.

  1. Question 1 of 30

    Which statement accurately describes a key difference between final and const in Dart?

    Show the answer

    Answer: a · A final variable can hold a runtime value like DateTime.now(), while const requires a compile-time constant.

    final allows single assignment at runtime, so DateTime.now() is valid, whereas const requires a compile-time constant and deep immutability. Option D is wrong because final only prevents reassignment of the variable, not mutation of the object's contents.

    Read the full bite: What is the difference between final and const in Dart?

  2. Question 2 of 30

    Which statement accurately describes Dart's positional and named parameter rules?

    Show the answer

    Answer: c · Optional positional parameters use square brackets and must appear before named ones.

    The card states optional positional parameters use square brackets and must precede named ones, while named parameters use curly braces and can be required. D is the most tempting distractor because it repeats the common red-flag misconception that optional positional parameters use curly braces.

    Read the full bite: Explain Dart positional vs named parameters and write one signature

  3. Question 3 of 30

    In Dart, what is the result of building a Map<String, User> with {for (var u in users) u.id: u} when two users share the same id?

    Show the answer

    Answer: c · The last user encountered silently overwrites the previous entry

    Dart map literals silently overwrite duplicate keys, so the last user wins without throwing. Many candidates incorrectly assume a runtime exception occurs, but Dart LinkedHashMap simply replaces the previous value.

    Read the full bite: Convert List<User> to Map<String, User> keyed by user id

  4. Question 4 of 30

    Which statement accurately describes the difference between final and const fields when declared inside a Dart class?

    Show the answer

    Answer: c · const fields must be static, while final fields can be instance fields

    Inside a Dart class, const fields must be static because they are compile-time constants, whereas final fields may be instance-level since they are assigned once at runtime. Distractor A reverses this relationship, a red flag the card specifically identifies.

    Read the full bite: Difference between final and const Dart class properties?

  5. Question 5 of 30

    When deduplicating emails in Dart, why is emails.toSet().toList() preferred over manually looping with contains?

    Show the answer

    Answer: d · It preserves first-occurrence order and runs in average O(n) time instead of O(n^2)

    Converting to a Set uses Dart's LinkedHashSet to drop duplicates in average O(n) time while keeping the first occurrence of each email in its original position. Option B is tempting because distinct sounds like a standard operation, but it is not part of Dart's core Iterable API and comes from external packages like RxDart.

    Read the full bite: Deduplicate a List of emails in Dart

  6. Question 6 of 30

    Which statement accurately describes how to consume a Future<String> and handle errors idiomatically in Dart?

    Show the answer

    Answer: b · Use an async function with try/catch around an await, or chain .then() with .catchError() on the Future.

    Option B correctly identifies both callback-style and async/await patterns for handling values and errors. Option A is wrong because a Future<String> is a pending object, not an actual String, so assigning it directly causes a type mismatch and synchronous try/catch cannot catch its asynchronous errors.

    Read the full bite: Define a Dart Future, return Future<String>, and handle errors with both patterns.

  7. Question 7 of 30

    What is the practical consequence of declaring an async Dart function as void instead of Future<void>?

    Show the answer

    Answer: a · The caller gets no Future handle, so they cannot await completion or catch async errors.

    A void return type hides the implicit Future from the caller, which prevents awaiting completion and catching errors with try/catch. Option C is tempting but wrong because without a Future handle, exceptions become uncaught async errors instead of propagating to the caller.

    Read the full bite: Difference between Future<void> and void from an async function

  8. Question 8 of 30

    You need to build a Flutter button that increments a local counter and updates its label each time it is pressed. Which design choice follows Flutter's widget model correctly?

    Show the answer

    Answer: c · Use a StatefulWidget because the mutable counter belongs in the State object, which persists across rebuilds while the widget stays immutable.

    The correct answer reflects the two-class architecture: the immutable widget is recreated, but the State object persists and owns mutable data like a counter. Distractor B is tempting because beginners often believe the StatefulWidget class itself stores mutable fields, yet the card clarifies that mutability lives only in the separate State object.

    Read the full bite: Explain StatelessWidget vs StatefulWidget and when to choose each

  9. Question 9 of 30

    Which of the following is safe to do inside a State object's build method?

    Show the answer

    Answer: c · Read inherited properties like Theme from BuildContext and return a widget

    Build must remain a pure, declarative function that returns a widget based on current state and context, so reading inherited data is appropriate. Fetching data, mutating state, or initializing controllers are side effects that violate the declarative contract and belong in lifecycle methods like initState.

    Read the full bite: What is the build method's purpose and key constraints?

  10. Question 10 of 30

    You need equal spacing before the first child, between children, and after the last child in a Row. What is the correct approach?

    Show the answer

    Answer: c · Set mainAxisAlignment to MainAxisAlignment.spaceEvenly

    MainAxisAlignment.spaceEvenly divides all free horizontal space into equal gaps before, between, and after children. spaceBetween is a tempting distractor because it only places free space between children, leaving the edges flush.

    Read the full bite: In a Row, how do you space children evenly across the width?

  11. Question 11 of 30

    Which widget configuration correctly splits a Column's available space into one-third and two-thirds using Expanded?

    Show the answer

    Answer: c · Wrap both children in Expanded with flex values of 1 and 2

    Expanded allocates a Column's leftover space proportionally by flex ratio, so values 1 and 2 produce a 1/3 and 2/3 split. Option A is tempting but wrong because flex factors are relative integers, not percentages, and option D is incorrect because Flexible lets children shrink rather than forcing them to fill their share.

    Read the full bite: How do you split a Column 1/3 and 2/3 using Expanded?

  12. Question 12 of 30

    In a Row, which property controls whether crossAxisAlignment.end aligns children to the bottom?

    Show the answer

    Answer: a · verticalDirection

    In a Row, the cross axis is vertical, so verticalDirection determines whether crossAxisAlignment.end means bottom or top. textDirection governs the horizontal main axis, not the vertical cross axis, which is why conflating the two is a common mistake.

    Read the full bite: mainAxisAlignment vs crossAxisAlignment in Column, and textDirection in Row

  13. Question 13 of 30

    Which approach correctly adds both tap handling and horizontal drag support to a plain Container?

    Show the answer

    Answer: a · Wrap it in a GestureDetector and implement the tap and drag callbacks, because GestureDetector exposes both types of callbacks while InkWell does not support drags.

    GestureDetector exposes callbacks for taps, drags, scales, and pans without imposing visual effects, whereas InkWell is limited to tap feedback and requires a Material ancestor to render its ripple. Option B is tempting because InkWell does need Material, but it does not expose drag callbacks, so it cannot satisfy the requirement.

    Read the full bite: Handle taps on a non-button Container: GestureDetector vs InkWell

  14. Question 14 of 30

    Which approach correctly listens to a TextField's changes and ensures resources are cleaned up when the widget is destroyed?

    Show the answer

    Answer: d · Create a TextEditingController, attach it to the TextField, listen with addListener, and dispose it in State.dispose

    A TextEditingController with addListener and dispose is correct because it provides lifecycle-safe listening and imperative access to the text. The onChanged option is tempting but wrong because it only fires a callback and does not give you a way to read the current value programmatically later.

    Read the full bite: How do you retrieve and listen to TextField changes in Flutter?

  15. Question 15 of 30

    In Flutter, when will a TextFormField inside a Form display the error text returned by its validator?

    Show the answer

    Answer: b · Only after formKey.currentState.validate() is explicitly called

    Calling validate() on the FormState walks the form tree and executes each registered validator, rendering any returned string as inline error text. A is tempting because beginners often assume onChanged triggers validation, but keystrokes alone do not run the validator.

    Read the full bite: Explain the validator property in TextFormField and what triggers error display

  16. Question 16 of 30

    How should a parent screen correctly capture data sent back from a route it pushed with Navigator.push?

    Show the answer

    Answer: c · Await the Future returned by Navigator.push, which completes with the Navigator.pop result.

    Navigator.push returns a Future that completes with the value passed to Navigator.pop, so awaiting it is the correct pattern. Reading it synchronously fails because the route is still active and the result is not yet available.

    Read the full bite: How do you pass data with Navigator.push and return data with Navigator.pop?

  17. Question 17 of 30

    Which statement accurately describes a tradeoff of using Navigator.pushNamed instead of Navigator.push?

    Show the answer

    Answer: b · It centralizes route definitions but sacrifices compile-time type safety for arguments.

    Navigator.pushNamed centralizes routes in a single map, but its arguments parameter is dynamic, requiring casting or wrapper classes to stay safe. Option C is wrong because named routes do not automatically handle complex objects; passing them without casting creates runtime errors and maintenance burden.

    Read the full bite: Navigator.push vs Navigator.pushNamed in Flutter

  18. Question 18 of 30

    Which scenario correctly describes when to use setState rather than a dedicated state management solution?

    Show the answer

    Answer: d · Tracking the current page index in a PageView that only one screen uses

    The page index is ephemeral state local to one widget, making setState the ideal synchronous choice. Option C describes a common anti-pattern—hoisting data through constructor layers with setState creates tight coupling and rebuild issues, which is exactly when you should reach for a state management library instead.

    Read the full bite: Explain ephemeral vs app state and when to use setState

  19. Question 19 of 30

    What is the most accurate description of how the Provider package relates to InheritedWidget?

    Show the answer

    Answer: d · Provider is a wrapper over InheritedWidget that adds lifecycle and ergonomics

    Provider builds directly on InheritedWidget, adding boilerplate reduction, disposal, and scoped reads. It is not an independent store, so the reactive-store option is a common misconception.

    Read the full bite: Provider package versus raw InheritedWidget

  20. Question 20 of 30

    Which statement accurately describes the proper way to parse a JSON list from an HTTP GET response in Dart?

    Show the answer

    Answer: d · Construct a Uri with Uri.parse, await http.get, check that statusCode equals 200, then decode and cast the body to List<Map<String, dynamic>>

    Option D is correct because package:http requires a Uri, verifying statusCode 200 prevents decoding error pages, and casting to List<Map<String, dynamic>> gives the compiler the concrete collection shape. Option C is tempting because it includes the right cast, but passing a raw string is invalid and skipping the status check risks decoding a non-JSON error response.

    Read the full bite: Make a GET request with http and parse JSON in Dart

  21. Question 21 of 30

    Where should the Future be created when using FutureBuilder to avoid restarting async work on every rebuild?

    Show the answer

    Answer: c · In initState, didUpdateWidget, or didChangeDependencies, then stored in state

    Storing the Future in state during initState or didUpdateWidget gives FutureBuilder a stable reference that survives rebuilds. Creating it inside build is the most common mistake because build can run every frame, restarting the async work repeatedly.

    Read the full bite: Explain FutureBuilder and how it manages async UI states

  22. Question 22 of 30

    When implementing JSON deserialization in a Dart model class, why is a factory constructor typically chosen over a generative constructor?

    Show the answer

    Answer: c · They allow validation and transformation of JSON values before the main constructor handles field assignment.

    A factory constructor centralizes deserialization and lets you preprocess raw JSON values before passing clean data to the primary constructor. The claim that Dart requires a factory for fromJson is a common misconception, since generative constructors can technically parse JSON but lack the same flexibility for arbitrary preprocessing.

    Read the full bite: Purpose of factory fromJson constructor in Dart models

  23. Question 23 of 30

    A Flutter app must persist auth tokens and a growing list of categorized tasks with due dates. Which persistence strategy is most appropriate?

    Show the answer

    Answer: b · Use shared_preferences for tokens and SQLite for the tasks.

    The card states key-value storage is meant for primitives like auth tokens, while structured relational data such as categorized tasks justifies SQLite for complex queries and sorting. Choosing SQLite for simple tokens adds unnecessary build size and complexity, and storing structured data as JSON blobs makes filtering and aggregation painful.

    Read the full bite: When to use SQLite over key-value storage?

  24. Question 24 of 30

    You need to animate a container's padding and border radius whenever a user toggles a setting. Which approach minimizes boilerplate while correctly handling the animation lifecycle?

    Show the answer

    Answer: d · Use an AnimatedContainer, pass the new padding and decoration values on rebuild, and configure the duration and curve through its constructor.

    AnimatedContainer is an implicitly animated widget that automatically tweens to new property values on rebuild while managing its own internal AnimationController, making it the simplest choice for state-driven padding and radius changes. Option A is tempting but wrong because using an explicit controller for a simple property transition introduces unnecessary StatefulWidget boilerplate and contradicts Flutter's declarative philosophy.

    Read the full bite: Implicit vs explicit animations: AnimatedContainer or AnimationController?

  25. Question 25 of 30

    When implementing a static blue circle with CustomPaint, why is it important that shouldRepaint returns false?

    Show the answer

    Answer: b · It tells Flutter to skip repainting when the painter's properties haven't changed, preserving GPU performance.

    Returning false lets Flutter cache the rasterized picture and avoid wasting GPU time when the painter is unchanged. Option C is wrong because the build phase finishes before paint begins, so shouldRepaint has no effect on widget rebuilding.

    Read the full bite: Describe CustomPaint and CustomPainter and implement a circle

  26. Question 26 of 30

    Which statement accurately describes the division of labor between AnimationController and TickerProvider?

    Show the answer

    Answer: d · AnimationController defines the animation state and value, while TickerProvider supplies the per-frame heartbeat via a Ticker.

    AnimationController owns the animation value, bounds, and playback direction, but it needs TickerProvider's Ticker to receive frame callbacks and update those values over time. Option A is tempting but wrong because TickerProvider is a required dependency, not an optional optimization.

    Read the full bite: How do AnimationController and TickerProvider work together to drive animations?

  27. Question 27 of 30

    Which native setup is required for the Flutter camera plugin beyond adding it to pubspec.yaml?

    Show the answer

    Answer: d · iOS: NSCameraUsageDescription and NSMicrophoneUsageDescription; Android: minSdkVersion 24 for CameraX

    The plugin does not auto-configure native layers: iOS requires both NSCameraUsageDescription and NSMicrophoneUsageDescription strings in Info.plist, and Android's default CameraX implementation requires minSdkVersion 24. Option C is tempting because it names a real iOS key but omits the microphone description and confuses compileSdk with minSdk, while D reflects the common misconception that Flutter handles native permissions automatically.

    Read the full bite: What native iOS and Android config does the Flutter camera plugin need?

  28. Question 28 of 30

    What accurately describes how a MethodChannel carries a method call from Dart to native code?

    Show the answer

    Answer: c · Dart serializes the call into a message, sends it asynchronously over a named channel, and receives a Future while native processes it on the main thread.

    MethodChannel is an async message-passing bridge: Dart encodes the call, the binary messenger ferries it to the native main thread, and the result returns as a Future. Option A is wrong because calls are not synchronous direct bindings like JNI, and option B is tempting because matching names are required, but data is serialized rather than passed as raw pointers.

    Read the full bite: Explain the purpose of MethodChannel and how it enables Dart-to-native calls

  29. Question 29 of 30

    You need to verify a button tap updates text on one Flutter screen without launching a device. Which statement about the correct test approach is true?

    Show the answer

    Answer: b · It uses WidgetTester to pump the screen in a headless environment

    Widget tests use WidgetTester to pump widgets into a simulated headless environment, so you can verify UI interactions without a device or emulator. The emulator option is tempting but wrong because running on a real device or emulator defines an integration test, not a widget test.

    Read the full bite: Unit, widget, and integration test differences in Flutter

  30. Question 30 of 30

    Which two-step pattern correctly separates locating a 'Hello' text widget from asserting that exactly one exists?

    Show the answer

    Answer: d · Store find.text('Hello') in a finder and pass it to expect with findsOneWidget.

    Option D respects the framework's separation of concerns by using a Finder to search the tree and a Matcher to assert exactly one result. Option B is a frequent beginner mistake that compiles but performs no meaningful assertion because the matcher is missing.

    Read the full bite: How do you verify a Text widget with 'Hello' is present?

Could you explain these out loud?

That is what an interview actually tests. Tezvyn gives you questions like these with what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.

The iPhone app is on the way

We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.

Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.

Get it on Google PlayiPhone app coming soon