Dart
Dart is the language under Flutter: sound null safety, classes with mixins and modifiers, records and patterns, futures, streams and isolates. Flutter interviews open here before widgets.
on this pageshowhide
guide
overview
~1 minDart interviews usually arrive bundled with Flutter, and the language rounds check whether you can read and write the code under the widgets rather than recite framework APIs. Openers test precision on small things: `final` against `const`, nullable against non-nullable types, what a tear-off is. The middle of the round is the object model and asynchrony — how classes double as interfaces, how mixins and the Dart 3 class modifiers shape reuse, and how futures, streams and the event loop keep an app responsive on one thread. Senior rounds move to modelling with sealed types and patterns, to why generics that keep their types at run time can still fail at run time, to isolates for real parallelism, and to the packaging and build decisions a team lives with. The hub follows those seams. The language core is [Everyday Syntax](/topics/lang-dart-types-syntax), [Sound Null Safety](/topics/lang-dart-null-safety), [Object-Oriented Features](/topics/lang-dart-classes-mixins), [Generic Types](/topics/lang-dart-generics), [Functional Style](/topics/lang-dart-functional) and [Destructuring & Matching](/topics/lang-dart-records-patterns). Data work sits in [Collections](/topics/lang-dart-collections) and [Platform Libraries](/topics/lang-dart-core-libs). Concurrency is [Asynchrony](/topics/lang-dart-futures-async) first, then [Isolates & Concurrency](/topics/lang-dart-isolates). The working-engineer layer is [SDK Tooling](/topics/lang-dart-tooling) and [Packages & Pub](/topics/lang-dart-packages). Learn syntax and null safety before anything else: nearly every later answer assumes you read `String?` as its own type and know where the compiler stops protecting you. Classes and collections come next, since they make up most daily code, then asynchrony, which Flutter questions reach within minutes. Records and patterns reward a pass once classes feel routine, because sealed hierarchies join the two. Leave isolates, generic variance and package publishing for last unless the role names them: a team shipping heavy on-device work, or one that maintains its own packages.
primer
### The type system is sound, and null is part of it A variable of type `String` cannot hold null; `String?` can, and the compiler makes you deal with the difference before use. Soundness is the stronger promise: the static type is trusted at run time, not merely suggested. Flow analysis promotes a nullable variable after a test, but only where it can prove nothing changed in between. The escape hatches — `!`, `late`, `dynamic` — each move a check from compile time to run time — interviewers want to hear which one you are paying for. ### Every class is also an interface Dart has single inheritance, no separate interface declaration, and an implicit interface for every class: another class can take the signatures and none of the code. Mixins add reusable members without a second superclass, and extension methods add members to types from other packages without changing them. Dart 3's class modifiers let a library author restrict what outside code may do with a type, closing the old gap where any public class could be implemented or extended by anyone. ### Final binds a name; const fixes a value `final` stops reassignment; `const` means the value is known at compile time, is deeply immutable and is shared rather than rebuilt. Neither tells you whether the object behind a `final` variable can change. Flutter leans on the distinction: a `const` widget is one shared instance, which the framework can recognise as unchanged when its parent rebuilds. ### One thread per isolate, one event loop per thread Dart code runs on a single thread inside an isolate, driven by an event loop with two queues. `async` and `await` make waiting cheap; they do not make computing parallel. A `Future` is one value arriving later, a `Stream` is a sequence of them, and both come down to callbacks scheduled on that loop. When work is CPU-bound, the answer is another isolate: separate memory, its own loop, and communication only by messages. ### Generics keep their types Type arguments survive to run time, so a `List<int>` knows what it is. That makes type tests against generic types work, and it also means a list created as `List<dynamic>` stays one however well-typed its contents look. Generic types are also covariant: some writes the compiler accepts are refused by a check at run time instead. ### Dart 3 made data modelling first-class Records give anonymous, typed tuples; patterns test and destructure values in `switch`, `if-case` and declarations; `sealed` classes let the compiler check that a switch covers every subtype. Together they replace chains of `is` checks and hand-written result classes, and fluency with them is how interviewers tell current Dart from pre-2023 Dart. ### One source, several targets The same code runs JIT-compiled on the VM during development, the basis of hot reload, and ships AOT-compiled to native code, or compiled to JavaScript or WebAssembly for the web. Available platform libraries differ by target, and runtime reflection is not available to Flutter apps, so the ecosystem generates code ahead of time instead.
- Sound null safety
- The rule that non-nullable types exclude null and that static types hold at run time, so a checked program cannot meet an unexpected null.
- Type promotion
- Flow analysis narrowing a variable to a more specific type, such as nullable to non-null, after a check the compiler can prove still holds.
- late variable
- A non-nullable variable declared without an initializer and checked on first read at run time; with an initializer, it computes that value lazily on first access.
- Implicit interface
- The interface every Dart class defines just by existing, made of its instance members, so any other class can implement it without inheriting code.
- Mixin
- A reusable bundle of members applied to a class with the with clause, sharing behaviour without a second superclass.
- Class modifier
- A keyword such as base, interface, final or sealed that limits how code outside the declaring library may extend, implement or construct a class.
- Sealed class
- An implicitly abstract class whose direct subtypes must live in the same library, so the compiler knows them all and can check switches for exhaustiveness.
- Const canonicalization
- The rule that equal compile-time constant expressions produce one shared instance, so two identical const objects are the same object.
- Record
- An anonymous, immutable aggregate of positional and named fields, each with its own static type, compared by structure rather than identity.
- Pattern
- Syntax that tests a value's shape and binds parts of it to variables, used in switches, if-case statements and variable declarations.
- Future
- An object standing for one value or error that becomes available later; await pauses an async function until it completes.
- Stream
- An asynchronous sequence of events, single-subscription with one listener or broadcast with many, consumed through a subscription that can be paused or cancelled.
- Microtask queue
- The event loop's higher-priority queue, drained completely before the next event is taken from the main event queue.
- Isolate
- An independent Dart execution context with its own memory and event loop; isolates communicate only by passing messages through ports.
- Tear-off
- A reference to a function, method or constructor used as a value without calling it, such as print or User.new.
- Reified generics
- Type arguments that stay attached to objects at run time, so a type test against a generic type, such as a list of strings, works.
- build_runner
- The package that runs code generators and writes their output as source files beside yours, the ecosystem's substitute for runtime reflection.
The sections stack. Everyday syntax and null safety define what a value is; the object model decides how values are shaped and shared; generics and functional style are the abstraction tools that collections, streams and callbacks all rest on. [Collections](/topics/lang-dart-collections) are generic classes driven by closures, which is why a question about a lazy `map` result or a failed cast is really a question about [Iterables & Laziness](/topics/lang-dart-collections-iterables) or [Bounds & Reification](/topics/lang-dart-generics-type-params). Asynchrony reuses the same pieces. A future is a generic object completed later, a stream is a generic source of events consumed through callbacks, and `await` is the syntax that hides those callbacks. Isolates sit one layer out: they exist because the event loop is single-threaded, and what you may send between them is limited because they share no memory. [Platform Libraries](/topics/lang-dart-core-libs) bring outside data in as untyped values, decoded JSON above all, and [Destructuring & Matching](/topics/lang-dart-records-patterns) is the current way to check that data and turn it back into typed values. Tooling and packages form the outer ring. The compilation target decides which libraries you may import and whether reflection exists, which is why code generation carries so much weight. And because every class is an implicit interface, Pub's version constraints and the class modifiers together decide which changes to a published package count as breaking. A small example where several ideas meet: ```dart sealed class Shape {} class Square extends Shape { Square(this.side); final double side; } class Rect extends Shape { Rect(this.w, this.h); final double w, h; } double area(Shape s) => switch (s) { Square(:final side) => side * side, Rect(:final w, :final h) => w * h, }; (double, int) summarize(List<Shape> shapes) => (shapes.map(area).fold(0.0, (a, b) => a + b), shapes.length); ``` The `sealed` base lets the switch expression omit a default case; each object pattern checks the subtype and binds its fields in one step; the record return type carries two typed values without a wrapper class; and `shapes.map(area)` passes a tear-off where a lambda would only forward its argument. Add a `Circle` subtype and `area` stops compiling until it handles the new case.
- Everyday Syntax →
Variables and finality, built-in types, cascades and parameter kinds are the vocabulary every other section writes in; openers start here.
- Sound Null Safety →
Nullable types, promotion and the escape hatches reappear in nearly every later answer, and interviewers reach for them early.
- Object-Oriented Features →
Constructors, implicit interfaces, mixins and modifiers are the bulk of everyday modelling and of Flutter's own API surface.
- Collections →
Lists, maps, lazy iterables and collection literals are where most daily code, and many build methods, actually live.
- Asynchrony →
Futures, streams and the event loop explain how one thread stays responsive; Flutter rounds reach them within minutes.
- Destructuring & Matching →
Once classes feel routine, records, patterns and exhaustive switches show you write current Dart rather than pre-2023 Dart.
Reaching for the postfix
!whenever the analyzer flags a nullable value: it silences the check and turns a type error into a crash at run time — see Bang & Coalescing Operators.Calling a list held in a
finalvariable immutable: the binding is fixed, the object is not, and only an unmodifiable list refuses every write.Marking a CPU-heavy parse or image transform
asyncand expecting smooth frames: it still runs on the same thread, so move it to an isolate.Awaiting independent requests one after another: each waits for the previous, so the screen pays the sum of their latencies instead of the slowest one.
Casting a decoded JSON array straight to a typed list: it was created with a dynamic element type, reified generics keep it that way, and the cast throws.
Listening to a stream or creating a
StreamControllerwith no plan forcancelandclose: subscriptions outlive their screen and keep pushing events into disposed state.Reading
_nameas class-private: Dart privacy is per library, so everything in the same file sees it and your tests in another file do not.Writing
onPressed: _save()where a callback belongs: it runs the method while building and passes its result — see Closures & Tear-Offs.
This guide assumes Dart 3, where sound null safety is mandatory and records, patterns and class modifiers are part of the language. Interviewers still probe the releases that changed how code is written, mostly because older tutorials and packages predate them: - **2.7** — extension methods became stable. - **2.12** — sound null safety arrived, opted into per package, with a mixed-mode period while dependencies migrated. - **2.15** — constructor tear-offs such as `User.new`. - **2.17** — enhanced enums with fields and constructors, and super-initializer parameters. - **2.19** — `Isolate.run` for one-off background work. - **3.0** — records, patterns, switch expressions and class modifiers including `sealed`; code without sound null safety no longer runs. - **3.2** — private final fields became eligible for type promotion. - **3.3** — extension types, zero-cost wrappers over an existing representation. - **3.7** — the formatter adopted a new style that adds and removes trailing commas itself. The release most likely to surface indirectly is 3.0: an answer that reaches for a hand-written result class and `is` chains, where a sealed hierarchy and a switch expression would do, reads as pre-2023 Dart.
Google makes both Dart and Flutter. Most engineers meet the language through Flutter, where widgets are Dart classes, build methods are Dart expressions, and async work is Dart futures and streams, so Flutter rounds often spend their first stretch on the language before any widget question. Expect to place Dart in three settings. For **cross-platform apps**, Flutter competes with React Native, which drives native UI components from JavaScript or TypeScript, and with Kotlin Multiplatform, which shares logic while each platform typically keeps its own UI; Flutter instead draws its own UI from one Dart codebase. For **the web**, Dart compiles to JavaScript or WebAssembly, and the natural comparison is TypeScript: both add static types to web code, but TypeScript's types are erased and deliberately unsound, while Dart's are checked and sound. **Outside Flutter**, Dart runs command-line tools and servers on the VM or as native executables, a smaller niche where Go and Node.js are the usual alternatives. The contrast most often requested is with Kotlin or Swift, since mobile teams hire across all three: each has null-aware types, but Dart runs code in isolates that share no memory, where the other two run threads over a shared heap.
explore
- Everyday Syntax31 questions
- Variables & Finality6 questions
- Built-In Types6 questions
- Operators & Cascades4 questions
- Loops & Branching4 questions
- Functions & Parameters6 questions
- Exceptions & Errors5 questions
- Sound Null Safety14 questions
- Nullable Types & Promotion5 questions
- Bang & Coalescing Operators4 questions
- Late & Required5 questions
- Object-Oriented Features35 questions
- Constructors & Initializers5 questions
- Extends & Implicit Interfaces5 questions
- Mixins & Linearization5 questions
- Class Modifiers5 questions
- Extension Methods & Types5 questions
- Equality & Operators5 questions
- Enhanced Enums5 questions
- Generic Types9 questions
- Bounds & Reification5 questions
- Covariance & Inference4 questions
- Destructuring & Matching13 questions
- Positional & Named Records4 questions
- Pattern Kinds5 questions
- Switch Expressions & Exhaustiveness4 questions
- Collections18 questions
- Built-In Containers4 questions
- Iterables & Laziness4 questions
- Conditional & Spread Literals5 questions
- Unmodifiable Views5 questions
- Functional Style9 questions
- Closures & Tear-Offs4 questions
- Function Types & Callables5 questions
- Asynchrony26 questions
- Futures & Await6 questions
- Event & Microtask Queues4 questions
- Single & Broadcast Streams5 questions
- Stream Controllers & Transformers6 questions
- Zones, Completers & Timers5 questions
- Isolates & Concurrency10 questions
- Spawning Workers5 questions
- Ports & Message Copying5 questions
- Platform Libraries17 questions
- Strings, Dates & URIs6 questions
- JSON & Codecs5 questions
- Files, Processes & Sockets6 questions
- SDK Tooling26 questions
- Command-Line Workflow6 questions
- Native & Web Compilation5 questions
- Analyzer & Lints5 questions
- Build Runner Generators5 questions
- Unit Test Runner5 questions
- Packages & Pub25 questions
- Libraries & Imports6 questions
- Pubspec Constraints5 questions
- Lockfile & Resolution5 questions
- Publishing & Scoring5 questions
- Shared-Lockfile Workspaces4 questions
questions
233 · 12 sectionsIn Dart, how does a variable typed dynamic differ from one typed Object?, and how do is, is! and as fit in?
basics
~20 sIn Dart, Object? and dynamic both accept any value, including null, but Object? keeps static checking: you test with is or cast with as before using String members. dynamic switches checking off, so calls compile and fail only at runtime.
In a Dart 3 switch statement, do cases fall through, and when do you still write break or continue inside a case?
basics
~20 sDart 3 switch statements never fall through from a non-empty case: its body runs and control leaves the switch, so no break is needed. Empty cases share the next body, and continue with a label jumps into another case.
In Dart, how do try, on, catch (e, st) and finally fit together, and when do you use on versus catch?
basics
~20 sIn Dart, on Type picks which thrown objects a clause handles, catch (e, st) binds the object and its StackTrace, the first matching clause in source order wins, and finally runs whether or not anything was thrown.
In Dart, how do required positional, optional positional [ ] and named { } parameters differ, and when do you choose named ones?
basics
~20 sDart functions take required positional parameters first, then either optional positional ones in [ ] or named ones in { }, never both; optional ones need a constant default or a nullable type. Named parameters read clearly and can be skipped individually.
In Dart, how do the /, ~/ and % operators differ on int operands, and what do ~/ and % give for negative numbers?
basics
~20 sIn Dart, / always returns a double, ~/ returns an int truncated toward zero (-7 ~/ 2 is -3), and % is Euclidean modulo whose result is never negative (-5 % 3 is 1); remainder() gives the sign-following remainder.
In Dart, what does the late modifier do on a non-nullable variable, and what happens if you read it before assigning it?
basics
~10 slate lets a non-nullable variable be declared without an initializer and assigned later. Dart checks it at runtime instead, so reading it before any assignment throws a LateInitializationError rather than producing null.
In Dart, what do the ?., ?? and ??= operators do, and when is each one the right tool?
basics
~20 sIn Dart, a?.b reads b only when a is non-null and otherwise yields null; a ?? b yields a unless it is null, evaluating b only then; a ??= b assigns b only when a is currently null.
In Dart's sound null safety, what is the difference between String and String?, and what does 'sound' guarantee at run time?
basics
~20 sIn Dart, String can never hold null while String? holds a String or null, so members like length need a check first. Sound means the guarantee holds at run time: an expression whose static type is non-nullable never evaluates to null.
In Dart, what does the postfix ! operator do at run time, and why does it hand the null risk back to you?
basics
~20 sIn Dart, the postfix ! casts a nullable expression to its non-nullable type; if the value is null it throws a TypeError, 'Null check operator used on a null value'. The compiler stops checking, so a wrong assumption becomes a runtime crash.
In Dart, why does a null check on a nullable field often not promote it, and how do local copies or private final fields help?
basics
~20 sIn Dart, a public field may be overridden by a getter and a non-final one reassigned between check and use, so flow analysis cannot promote it. Copy it into a local, or since Dart 3.2 make it private and final.
In Dart, what can a factory constructor do that a generative constructor cannot, and what are its limits?
basics
~20 sA factory constructor runs arbitrary code and then returns an instance it chooses: a cached object, a subtype, or one built via another constructor. It cannot use this or an initializer list, cannot return null, and cannot be called with super.
In Dart, what do an enum value's index and name return, and how do you list all values and look one up from a string?
basics
~20 sindex is the value's zero-based position in the declaration and name is its source identifier as a String. The generated static values list holds every value in order; values.byName('x') finds one by name and throws ArgumentError when none matches.
In Dart, why does [1, 2] == [1, 2] evaluate to false, and how do you compare two lists by their contents?
basics
~20 sDart's List keeps identity equality: == is true only for the same list object, and every non-const literal creates a new one. Compare contents with Flutter's listEquals, package:collection's ListEquality, or a length check plus element loop.
In Dart, what is an extension method, how do you declare one with `extension ... on`, and what may it contain?
basics
~20 sAn extension method adds a member to an existing type, including types you do not own, via extension Name on Type { ... }. It may declare methods, getters, setters, operators and static members, but no instance fields, constructors or abstract members.
In Dart, what is the difference between extends and implements, and what must a class that implements another class re-declare?
basics
~20 sextends makes a subclass that inherits the superclass's implementation, and a class has exactly one superclass. implements only adopts the implicit interface of each listed class, so the class must itself implement every instance member, fields included, but not constructors or statics.
In Dart, how do you declare a generic class and a generic method, for example a Page<T> wrapper for paginated API responses?
basics
~20 sPut type parameters in angle brackets after the name: class Page<T> { final List<T> items; } or R transform<R>(...). Callers pass Page<Order> or let inference pick the argument, and every use of T is then checked statically.
In Dart, what does it mean that generics are reified, and what can code do with a type parameter like T at run time?
basics
~20 sReified means every generic object keeps its type arguments at run time, so is List<String> checks, x is T tests and <T>[] literals work. T still cannot be constructed or used to call static members.
In Dart, what element types does inference give `var a = [];`, `var b = [1, 2.5];` and `List<int> c = [];`, and why?
basics
~10 sa is List<dynamic> because nothing constrains it, b is List<num> because upward inference takes the upper bound of int and double, and c is List<int> because the declared type flows down into the literal.
In Dart, what does a type-parameter bound such as T extends Object or T extends Identifiable allow, and what applies when no argument is given?
basics
~20 sA bound restricts type arguments to subtypes of the bound and lets generic code call the bound's members on T. T extends Object excludes nullable types. When an argument is omitted and nothing infers it, Dart instantiates to the bound.
In a Dart Page<T>.fromJson, why does casting json['items'] to List<Map<String, dynamic>> throw even though every element is a map, and how do you fix it?
basics
~10 sjsonDecode creates a List<dynamic>, and reified generics mean it stays List<dynamic> whatever it contains, so as List<Map<String, dynamic>> fails. Treat it as List<dynamic> and convert each element, or use cast, List.from or whereType.
In Dart 3, how do you return both the minimum and maximum temperature from one function, and how does the caller read them?
basics
~20 sDeclare a record return type such as ({double min, double max}) and return (min: lo, max: hi). The caller reads range.min and range.max, or $1 and $2 for positional fields, with each field keeping its static type.
In Dart 3, how does a switch expression differ from a switch statement, and where may a switch expression appear?
basics
~20 sA Dart 3 switch expression yields a value: cases are pattern => expression, comma-separated, _ is the only default, and it must be exhaustive. A switch statement runs statements and is exhaustiveness-checked only on types like enums, bool and sealed classes.
In Dart 3, how would you validate and destructure a decoded weather-API JSON map with if-case, and what does each part of the pattern check?
basics
~20 sWrite if (json case {'name': String city, 'main': {'temp': num temp}}). It checks that json is a map with those keys and value types, binds city and temp only on a full match, and otherwise runs the else branch.
In Dart 3, how would you model a PaymentResult as a sealed class hierarchy and handle every outcome with an exhaustive switch?
basics
~20 sDeclare sealed class PaymentResult with one subclass per outcome in the same library, each holding its own data, then switch over it with one object pattern per subtype and no wildcard. The compiler proves coverage and flags every switch when an outcome is added.
In Dart 3, how do you pull the fields of a returned record or an object's getters into local variables with a pattern?
basics
~20 sWrite a pattern variable declaration: var (city, temp) = latestReading(); for a positional record, final (:city, :temp) = ... for named fields, and var Forecast(:high, :low) = forecast; to read an object's getters into new locals.
In Dart, what is the difference between a growable and a fixed-length List, and which does List.filled create by default?
basics
~20 sA growable Dart List can add and remove elements; a fixed-length one only lets you overwrite them, and length changes throw UnsupportedError. List.filled and List.empty default to fixed-length, while literals, List.of and List.generate are growable.
In Dart, what is the difference between an Iterable and a List, and why does list.map(...) not give you a List?
basics
~20 sA Dart Iterable is any sequence you can step through; a List adds indexing, a stored length and mutation. map, where and similar methods return a lazy Iterable that computes nothing until iterated, so you call toList() to get a List.
In Dart, how do collection if elements and the spread operator let a Flutter build method assemble a children list without a temporary list?
basics
~20 sA collection if element adds its element only when the condition is true, and a spread ... inserts every element of another iterable in place, so a whole children list, conditional groups included, is one declarative literal instead of a mutable list.
In Dart, why can code still call add() on a list held in a final variable, and what actually makes a list unmodifiable?
basics
~20 sfinal only stops the variable from being reassigned; the list object it points to stays growable. A list rejects writes only when the object itself is unmodifiable: a const literal, a List.unmodifiable copy or an UnmodifiableListView, and then writes throw UnsupportedError at runtime.
When counting word frequencies in a Dart Map<String, int>, how do update, putIfAbsent and the [] operator differ?
basics
~20 sIn a Dart map, [] returns a nullable value, so counting needs counts[w] = (counts[w] ?? 0) + 1. update(w, (n) => n + 1, ifAbsent: () => 1) does it in one call; putIfAbsent returns the stored value and suits get-or-create grouping.
In Flutter, why is onPressed: _save() wrong while onPressed: _save and onPressed: () => _save() both work?
basics
~20 sonPressed expects a function to call later; _save() calls the method during build and passes its result, a void value the analyzer rejects. _save passes the method itself as a tear-off, and () => _save() passes an anonymous function that calls it.
In Dart, how do you write a function type such as `int Function(String)`, and where can you use one?
basics
~20 sA Dart function type is a function header with its name replaced by the keyword Function: int Function(String) accepts one String and returns an int. It can annotate parameters, fields, variables, return types and type arguments.
In Dart, what are function, method and constructor tear-offs such as forEach(print) and map(User.new), and when should a lambda stay instead?
basics
~20 sA tear-off names a function, method or constructor without parentheses, producing a function object that calls it: print, int.parse, buffer.write, User.new. Prefer it over a lambda that only forwards arguments; keep the lambda when arguments must be adapted or the receiver re-read.
In Dart, how would you type and compose a validator pipeline where each validator is a `String? Function(String)`?
basics
~10 sName the shape once with typedef Validator = String? Function(String value);, write factory functions that return configured validators, and a combinator that takes a List<Validator> and returns one Validator reporting the first non-null error.
In Dart, why is typing a callback parameter as plain `Function` weaker than a precise type such as `bool Function(String)`?
basics
~20 sPlain Function is the supertype of every function type and carries no signature, so calls through it are dynamic: arguments go unchecked until run time and the result is dynamic. A precise type like bool Function(String) is checked at compile time.
In Dart, what does a StreamController give you, and whose job is it to call close() on it?
basics
~10 sA StreamController pairs an input side (add, addError, addStream, close) with the stream it feeds. The code that creates the controller owns it and must close it; listeners only cancel their own subscriptions.
In Dart, what does a function marked `async` return to its caller, and what does `await` do inside it?
basics
~20 sAn async Dart function always returns a Future<T> immediately; returning a value completes it and throwing completes it with an error. Inside, await suspends the function until a future completes, then resumes with its value or rethrows its error.
In Dart, how does a StreamController.broadcast() controller behave differently from a default StreamController when events are added?
basics
~20 sA default controller allows one listener and buffers events added before it subscribes or while it is paused. A broadcast controller allows many listeners, drops events added while nobody listens, and lets each subscription buffer its own pauses.
In Dart, which APIs put work on an isolate's microtask queue versus its event queue, and which queue does the event loop drain first?
basics
~10 sEach isolate's event loop empties the microtask queue before taking the next event. scheduleMicrotask, Future.microtask and callbacks on completed futures are microtasks; Future(), Timer.run, Future.delayed, I/O and port messages are events.
In Dart, a dashboard loads profile, feed and stats from three independent futures; how do you run them concurrently and collect typed results?
basics
~20 sStart all three futures before awaiting any: Future.wait([a, b, c]) gives a List in argument order, and Dart 3's (a, b, c).wait gives a typed record. Awaiting one after another serialises the calls and sums their latencies.
In Dart, how do two isolates exchange data through SendPort and ReceivePort, and what happens to a mutable object you send?
basics
~20 sIsolates share no mutable state, so they talk by messages: a ReceivePort receives them, and its sendPort getter gives a SendPort that any isolate can call send() on. Mutable objects arrive as copies; immutable ones such as strings are shared.
In Dart, why doesn't marking a CPU-heavy function async keep the program responsive, and what does running it in another isolate change?
basics
~20 sAn async function still runs on the calling isolate's single thread; its synchronous work blocks that isolate's event loop until the next await. Another isolate has its own heap and event loop and can run the work in parallel on another core.
In Dart, which objects can you send through SendPort.send, and why does sending a closure sometimes fail with an illegal-argument error?
basics
~20 sBetween isolates sharing code, almost any object can be sent except native-resource holders (sockets, open files), ReceivePort, Finalizer and similar. spawnUri isolates accept only primitives, plain collections and ports. Closures fail when their captured context reaches something unsendable.
In Dart, when would you use Isolate.run and when Isolate.spawn, for example to hash thousands of files in a backup CLI?
basics
~20 sIsolate.run starts an isolate, runs one function, returns its result as a Future, rethrows its error, and exits. Isolate.spawn starts a long-lived worker from an entry point and a message, and you manage ports, results, errors and shutdown yourself.
Why does a Dart command-line program or worker isolate keep running after its work is done, and how do you close ports so it exits?
basics
~20 sAn open ReceivePort or RawReceivePort keeps its isolate alive, so a forgotten port stops a worker, or a CLI program, from exiting. Close each port with close() or by cancelling its subscription; tell a worker to close its own port.
In Dart, what does jsonDecode return, and why does decoded JSON need casts or patterns before you can use it as typed data?
basics
~10 sjsonDecode returns dynamic: objects become Map<String, dynamic>, arrays List<dynamic>, numbers int or double. Nothing is checked against your types, so you cast, convert lists with cast() or List.from, or validate with a pattern.
In Dart, what is the difference between int.parse and int.tryParse, and which should read a guest count typed into a booking form?
basics
~10 sint.parse throws a FormatException when the text is not a valid integer; int.tryParse returns null instead. For user input such as a guest count, use tryParse, handle null, then range-check the value.
In Dart, how does jsonEncode handle a custom settings object, and how do toJson(), toEncodable and JsonEncoder.withIndent produce pretty-printed JSON?
basics
~10 sjsonEncode writes numbers, strings, booleans, null, lists and string-keyed maps directly; for anything else it calls toEncodable, which by default calls the object's toJson(). For pretty output use JsonEncoder.withIndent(' ').convert(settings).
In Dart, how do UTC and local DateTime values differ, and how should a booking app parse, store and compare check-in times?
basics
~20 sA DateTime is anchored either in UTC or in the device's local zone, shown by isUtc. Store and send instants in UTC, convert with toLocal() only for display, and compare with isAtSameMomentAs or compareTo, since == also requires the same zone.
Why does a Flutter web build fail when code calls dart:io's Platform.isAndroid, and how do you branch between web and native code safely?
basics
~20 sdart:io wraps operating-system files, processes and sockets that a browser does not expose, so on the web its APIs, including Platform.isAndroid, are unsupported and fail at runtime. Check kIsWeb first, use defaultTargetPlatform, or split code with conditional imports.
How do you make a CI job fail when Dart code is not formatted, using dart format, and what does the command change by default?
basics
~20 sRun dart format -o none --set-exit-if-changed . in CI: it writes nothing and exits with code 1 if any file would change. Without flags, dart format rewrites files in place, wrapping to 80 columns and managing trailing commas.
In a Dart or Flutter project, what does dart run build_runner build do, and when do you use watch or clean instead?
basics
~20 sbuild_runner build runs every applicable builder once and writes outputs such as .g.dart parts beside your sources; watch keeps running and rebuilds incrementally on each save; clean deletes the build cache so the next build is a full one.
In Dart's package:test, how do test, group, setUp, tearDown and setUpAll organise a suite, and in what order do the hooks run?
basics
~20 stest declares one case; group nests cases under a name prefix. setUp runs before each test, outer groups first; tearDown runs after each test, even a failing one, inner groups first; setUpAll and tearDownAll run once per group.
In a Dart or Flutter analysis_options.yaml, what do include:, linter: rules, analyzer: errors: and analyzer: exclude: each control?
basics
~20 sinclude: pulls in shared option files such as a lint set; linter: rules switches individual lints on or off; analyzer: errors: changes a diagnostic's severity or ignores it; analyzer: exclude: removes files matching globs from analysis.
In Dart, how does JIT compilation on the Dart VM differ from AOT compilation, and when do you use each?
basics
~20 sJIT compiles Dart code while the VM runs it, which enables incremental recompilation, hot reload and rich debugging during development. AOT compiles to native machine code before shipping, giving consistent, short startup for production executables and apps.
In a Flutter app's pubspec.yaml, which versions do `http: ^1.2.0` and `http: ^0.13.6` allow, and how is each written without a caret?
basics
~20 sIn pub, ^1.2.0 allows >=1.2.0 <2.0.0, up to the next major, while ^0.13.6 allows >=0.13.6 <0.14.0, up to the next minor, because below 1.0 a minor bump may break. Written longhand, the range must be quoted.
In a Flutter or Dart pubspec.yaml, what decides whether a package belongs under `dependencies` or `dev_dependencies`, and what changes for your package's consumers?
basics
~20 sAnything imported from lib/ or bin/ must be a regular dependency; packages used only by tests, examples or tooling go in dev_dependencies. Pub installs your own dev dependencies but ignores the dev dependencies of every package you depend on.
In Dart, what does a leading underscore make private, and why can another class in the same file read a `_field` it does not own?
basics
~20 sA leading underscore makes a name private to its library, meaning the file plus any part files, not to its class. Every declaration in that library can use it, while other libraries, including your own tests, cannot.
In Dart's pub tool, what is the difference between `dart pub get` and `dart pub upgrade`, and how does each treat pubspec.lock?
basics
~20 sdart pub get keeps the versions already recorded in pubspec.lock and resolves only what is new or missing; dart pub upgrade ignores the lockfile and picks the newest versions the pubspec constraints allow, then writes a new lockfile.
In a published Dart 3 package, why is adding a method to a plain public class, or a subtype to a sealed class, a breaking change?
basics
~20 sDart classes are implicit interfaces, so a new member breaks users who implements the class, and a new sealed subtype or enum value breaks their exhaustive switches. Marking a class final stops outside subtyping, so its members can grow in minor releases.