Skip to content
tezvyn:

Top 30 Flutter Interview Questions and Answers

30 multiple-choice questions on Flutter, drawn from 30 bites out of the 294 tagged Flutter on Tezvyn. 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.

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 keyword is best for a variable initialized at runtime from an API call, never to change?

    Show the answer

    Answer: a · final

    The 'final' keyword is used for variables whose values are determined at runtime and assigned once, making them immutable thereafter. 'const' is incorrect because it requires the value to be known at compile-time, which is not the case for an API response.

    Read the full bite: Dart Variables: var, final, and const

  3. Question 3 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

  4. Question 4 of 30

    What is a direct consequence of Dart's principle that "everything is an object"?

    Show the answer

    Answer: c · Even basic data types like integers and strings have callable methods.

    The core idea is that even simple types like int and String are objects, meaning they come with built-in methods and properties, unlike primitive types in other languages. Dart does not have primitive types that need conversion; all values are objects from the start, and 'null' itself is an object of type 'Null'.

    Read the full bite: Dart's Core Data Types: Everything is an Object

  5. Question 5 of 30

    When accessing a property on a nullable object in Dart, what is the fundamental difference between using ?. and !?

    Show the answer

    Answer: c · ?. evaluates to null when the receiver is null, while ! casts to non-nullable and may throw at runtime.

    The null-aware operator ?. short-circuits and yields null if the receiver is null, whereas ! forcibly casts away nullability and throws a runtime exception if the value is actually null. Option D is wrong because it confuses ?. with the ?? default-value operator and incorrectly suggests ! is compile-time safe.

    Read the full bite: Describe Dart's null-aware ?. and null assertion ! operators

  6. Question 6 of 30

    What is the primary characteristic that makes Dart's arrow function syntax (=>) suitable for a function?

    Show the answer

    Answer: a · It implicitly returns the result of a single, concise expression.

    Arrow syntax is designed for functions that compute and return the result of a single expression, implicitly handling the return. Options A and B describe scenarios where a block body function is required, while option D incorrectly states that arrow syntax requires an explicit return keyword.

    Read the full bite: Dart Function Syntax: Block Body vs. Arrow Notation

  7. Question 7 of 30

    A class declares late final UserService repo and assigns it in initState. What happens if repo is read in build before that assignment?

    Show the answer

    Answer: a · A LateInitializationError is thrown at the point of access

    late shifts definite-assignment checks from compile time to runtime, so accessing the field before assignment throws LateInitializationError. Distractor C is tempting because that is exactly the compile-time error you would receive if the field were not marked late.

    Read the full bite: What problem does late solve in Dart?

  8. Question 8 of 30

    You need to store a collection of unique product SKUs that are currently in stock and frequently check if a particular SKU is available. Which Dart collection is the most efficient choice for this task?

    Show the answer

    Answer: a · Set, because it guarantees uniqueness and optimizes for fast existence checks.

    Set is specifically designed for storing unique items and provides highly efficient checks for an item's existence, making it ideal for this scenario. While a Map can also provide fast lookups, a Set is the most direct and efficient choice when only uniqueness and existence checking are required, without needing to associate a value.

    Read the full bite: Dart Collections: Choosing List, Set, or Map

  9. Question 9 of 30

    Given List<int> nums = [1, 2, 3, 4] and bool includeZero = true, which literal produces [0, 2, 4]?

    Show the answer

    Answer: a · [if (includeZero) 0, for (var n in nums) if (n.isEven) n]

    Option A correctly uses collection-if to prepend 0 and collection-for with a nested collection-if to filter evens inside one literal. Option B is tempting because where looks declarative, but without the spread operator it inserts the Iterable object itself as a single element rather than flattening its contents.

    Read the full bite: How do you use collection-if and collection-for to declaratively build a list?

  10. Question 10 of 30

    How does Dart's sound null safety fundamentally alter variable nullability?

    Show the answer

    Answer: b · Variables are non-nullable by default, requiring explicit opt-in for nullability.

    Dart's sound null safety makes variables non-nullable by default, meaning they are guaranteed to hold a value. To allow a variable to be null, developers must explicitly opt-in by adding a '?' to its type. Option D describes the opposite behavior, which is common in many other languages but not Dart with null safety.

    Read the full bite: Dart's Sound Null Safety: No More Null Errors

  11. Question 11 of 30

    Which statement accurately describes the primary function of Dart's null-aware access operator (?. )?

    Show the answer

    Answer: a · It safely attempts to access a member, returning null if the object itself is null.

    The null-aware access operator (?. ) safely checks if an object is null before attempting to access its members. If the object is null, the expression short-circuits and returns null, preventing a runtime error. Option D describes the if-null operator (??), and Option C describes the unsafe not-null assertion operator (!).

    Read the full bite: Dart's Null-Aware Operators: Safely Handle Nulls

  12. Question 12 of 30

    What is the primary advantage of using a sealed class instead of an enum for exhaustiveness-checked state machines in Dart 3?

    Show the answer

    Answer: c · Sealed classes let each subtype carry distinct constructor parameters and fields while keeping exhaustive switch safety.

    Sealed classes enable algebraic data types where each variant holds distinct payload data while the compiler verifies exhaustive handling, unlike enums which share a single shape. Distractor A is wrong because sealed subclasses must remain in the same library for the compiler to prove exhaustiveness; adding them elsewhere breaks that guarantee.

    Read the full bite: Explain Dart switch exhaustiveness for enums versus sealed classes

  13. Question 13 of 30

    When using Dart's cascade notation (..), what is a crucial difference compared to standard method chaining (.)?

    Show the answer

    Answer: c · The entire cascade expression evaluates to the original object, not the result of the last operation.

    The card explicitly states that the cascade expression gives back the original object, not the result of the final task, which is the crucial difference from standard method chaining. Option B is incorrect because cascade notation modifies the original object in place and returns it, rather than creating a new one.

    Read the full bite: Dart's Cascade Notation: Chain Calls on One Object

  14. Question 14 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

  15. Question 15 of 30

    What is the most direct consequence of calling an `async` function in Dart without using the `await` keyword?

    Show the answer

    Answer: a · The variable assigned the result will hold a `Future` object instead of the completed value.

    The card explicitly states that forgetting `await` results in receiving a `Future` object instead of the actual data, which can lead to downstream type errors. The `async` function itself still executes non-blockingly, and it doesn't immediately throw an exception or prevent execution.

    Read the full bite: Dart's async/await: Non-Blocking Code That Reads Synchronously

  16. Question 16 of 30

    What primary problem do Dart generics address in software development?

    Show the answer

    Answer: b · Allowing code to operate on different data types without sacrificing compile-time type safety.

    Generics solve the problem of writing code that works with various data types while maintaining type safety at compile time, preventing errors that would arise from using less specific types like Object or dynamic. Option A is incorrect because generics enforce type safety at compile-time, which is distinct from dynamic typing that defers type checking to runtime.

    Read the full bite: Dart Generics: Type-Safe Containers and Reusable Code

  17. Question 17 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?

  18. Question 18 of 30

    When is a Dart Stream the most appropriate choice for handling asynchronous data?

    Show the answer

    Answer: d · Processing a series of real-time sensor readings from an IoT device.

    Option D describes a continuous flow of data (real-time sensor readings), which is the primary use case for Dart Streams, as they handle sequences of asynchronous events over time. Options A, C, and D all represent scenarios where a single asynchronous value is expected, making a Future a more appropriate and simpler choice.

    Read the full bite: Dart Streams: Asynchronous Data Sequences

  19. Question 19 of 30

    Which statement accurately contrasts Dart's extends, implements, and with keywords for class reuse?

    Show the answer

    Answer: a · extends inherits from one superclass; implements requires reimplementing every public member; with injects behavior without subtyping.

    Option A is correct because extends provides single inheritance of implementation, implements forces the class to reimplement every public member itself, and with injects reusable behavior without creating an is-a relationship. Option B is wrong because extends does not allow multiple superclasses, implements does not reuse parent code, and with does not establish an is-a inheritance chain.

    Read the full bite: What are the key differences between Dart extends, implements, and with?

  20. Question 20 of 30

    Which statement accurately describes a semantic difference between a Dart factory constructor and a generative constructor?

    Show the answer

    Answer: c · A factory constructor can return an existing cached instance or a subtype, while a generative constructor always produces a fresh instance of the exact class.

    A factory constructor is not required to create a new instance and may return a cached object or subtype, whereas a generative constructor always allocates a fresh instance of the exact class. Option B is tempting because factories resemble static methods, but they remain part of the constructor namespace and are called with standard constructor syntax.

    Read the full bite: What is a Dart factory constructor and common use cases?

  21. Question 21 of 30

    You need to parse a dynamic JSON array into List<Product> where some objects may contain missing or mistyped fields. Which approach best preserves type safety and prevents runtime crashes?

    Show the answer

    Answer: a · Use a factory constructor that checks runtime types and defaults, then map over the list while isolating or skipping invalid rows.

    Defensive parsing inside a factory constructor centralizes validation and runtime type checks in the model layer, while isolating or skipping invalid rows during mapping prevents one malformed item from crashing the entire list. Option C spreads uncertainty by pushing null handling into the UI, and C fails because a Map cannot be directly cast to a custom class.

    Read the full bite: How do you model Product and safely parse JSON into List<Product>?

  22. Question 22 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.

  23. Question 23 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

  24. Question 24 of 30

    What is the primary benefit of Dart's `map()` and `where()` methods being lazy?

    Show the answer

    Answer: b · They reduce memory consumption by avoiding the creation of temporary intermediate lists.

    Lazy `map()` and `where()` methods defer computation until elements are actually requested, which prevents the creation of new, temporary lists for each step in a chain of operations. This significantly reduces memory overhead, especially for large datasets. Option C is incorrect because lazy iterables re-evaluate their operations each time they are iterated, unless explicitly materialized with `.toList()`.

    Read the full bite: Dart's Lazy Iterable Methods: map() and where()

  25. Question 25 of 30

    Which Dart constructor type is best suited for implementing a singleton pattern that returns a cached instance?

    Show the answer

    Answer: a · A factory constructor

    A factory constructor is designed to return an existing instance (e.g., from a cache) or a new one based on logic, making it ideal for singleton patterns. Named constructors always create new instances, and constant constructors focus on compile-time immutability and canonical instances, not runtime caching of a single instance.

    Read the full bite: Dart's Specialized Constructors: Named, Factory, and Constant

  26. Question 26 of 30

    In main(), sync prints 1 and 6 surround a Future(2), microtask(3), Future(4), and microtask(5). What is the output order?

    Show the answer

    Answer: d · 1, 6, 3, 5, 2, 4

    The event loop finishes all synchronous code first, then fully drains the microtask queue before processing any event queue callbacks, yielding 1, 6, 3, 5, 2, 4. Option B is tempting because it follows call order, but Dart strictly processes entire microtask batches before touching events.

    Read the full bite: Describe the Dart event loop and queue execution order

  27. Question 27 of 30

    Which Dart feature is best suited for defining an API contract that multiple unrelated classes must adhere to, without forcing them to inherit any shared implementation?

    Show the answer

    Answer: d · A regular class used as an implicit interface, implemented with the 'implements' keyword.

    An implicit interface, created from any regular class and used with 'implements', forces a class to provide its own implementation for every public member, ensuring an API contract without inheriting code. While an abstract class can define a contract (Option C), the card advises against using it if no code is shared, preferring a regular class as an interface for pure contracts.

    Read the full bite: Dart: Abstract Classes & Implicit Interfaces

  28. Question 28 of 30

    What happens when you call listen() again on a single-subscription Dart stream after the first listener has finished?

    Show the answer

    Answer: d · It throws a StateError because only one listener is ever permitted

    A single-subscription stream allows exactly one listener over its entire lifetime, so calling listen again throws a StateError even after the first listener completes. The idea that it resumes where the first left off is a common misconception because the runtime enforces the one-listener contract strictly, treating the stream as consumed rather than pausable.

    Read the full bite: Explain single-subscription vs broadcast Streams in Dart

  29. Question 29 of 30

    If a custom class overrides operator== but not hashCode, what is the primary consequence when its instances are used in a Set or as Map keys?

    Show the answer

    Answer: b · Hash-based collections may fail to correctly identify equal objects, leading to unexpected behavior like duplicates or missing elements.

    The core contract states that if two objects are equal by operator==, they must have the same hashCode. If hashCode is not overridden, two logically equal objects might have different hash codes, causing hash-based collections to treat them as distinct. This is a runtime logical error, not a compile-time error.

    Read the full bite: Why hashCode and operator== Must Be Overridden Together

  30. Question 30 of 30

    When using Future.wait to fetch user profiles concurrently, how do you isolate individual failures while preserving successful results?

    Show the answer

    Answer: b · Attach catchError to each future before passing the list to Future.wait, then filter out nulls afterward

    Attaching catchError to each future guarantees every item resolves, so Future.wait yields a full list where nulls represent failures that can be filtered out. Wrapping Future.wait in try-catch is a common mistake because it catches the batch error but discards all successful profiles that had already completed.

    Read the full bite: Fetch user profiles concurrently and handle individual failures

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