Skip to main content
The for statement is a control flow construct used to execute a block of code repeatedly. Dart supports three primary variations: the standard C-style loop, the for-in loop for iterables, and the asynchronous await for loop for streams.

Standard for Loop

The standard for loop consists of three clauses separated by semicolons: the initializer, the condition, and the final expression (often called the increment/decrement). Syntax
for (initialization; condition; final_expression) {
  // Statement(s) to execute
}
Execution Flow
  1. Initialization: Executed exactly once before the loop begins. It typically declares and initializes a loop counter variable.
  2. Condition: A boolean expression evaluated before every iteration. If true, the loop body executes. If false, the loop terminates.
  3. Loop Body: The block of code within the braces {}.
  4. Final Expression: Executed after every iteration of the loop body. It is typically used to update the loop counter.
Example
for (var i = 0; i < 3; i++) {
  print('Index: $i');
}

for-in Loop

The for-in loop simplifies iteration over objects that implement the Iterable interface (such as List, Set, or Map.keys). It handles the underlying iterator mechanics automatically. Syntax
for (var variable in iterable_expression) {
  // Statement(s) to execute
}
Execution Flow
  1. The iterable_expression is evaluated once.
  2. An Iterator is obtained from the iterable.
  3. The loop calls moveNext() on the iterator.
  4. If moveNext() returns true, the current value is assigned to variable, and the body executes.
  5. If moveNext() returns false, the loop terminates.
Example
final numbers = [10, 20, 30];

for (final number in numbers) {
  print(number);
}

Asynchronous await for Loop

The await for loop is used to iterate over the events of a Stream. This construct pauses execution of the enclosing async function until the next value is available from the stream. Syntax
await for (var variable in stream_expression) {
  // Statement(s) to execute
}
Execution Flow
  1. The loop waits for the stream to emit a value.
  2. When a value is emitted, it is assigned to variable, and the body executes.
  3. The loop continues until the stream sends a “done” event or the loop is explicitly broken.
Example
Future<void> readStream(Stream<int> stream) async {
  await for (final value in stream) {
    print(value);
  }
}

Control Transfer Statements

Dart provides keywords to alter the standard flow within a loop structure.
  • break: Immediately terminates the loop. Execution resumes at the first statement following the loop block.
  • continue: Skips the remainder of the current iteration.
    • In a standard for loop, control jumps to the final expression.
    • In a for-in loop, control jumps to the next iterator check.
Example
for (var i = 0; i < 10; i++) {
  if (i == 2) continue; // Skips iteration when i is 2
  if (i == 5) break;    // Terminates loop when i is 5
  print(i);
}

Variable Scope and Closure

Variables declared in the initialization clause of a for loop are lexically scoped to the loop body. Dart captures the value of the index for each iteration, ensuring that closures created inside the loop capture the specific value of the variable for that iteration, rather than a reference to the final value.
var callbacks = [];
for (var i = 0; i < 2; i++) {
  // 'i' is captured per iteration
  callbacks.add(() => print(i));
}

callbacks.forEach((c) => c()); // Prints 0, then 1
Master Dart with Deep Grasping Methodology!Learn More