Dart Tutorial

Dart Lesson 34 of 102 3 min read

Spread Operator, Collection if and Collection for in Dart

Build lists, sets and maps in Dart using the spread operator (...), null-aware spread, collection if and collection for.

On this page

Dart lets you put a little logic directly inside a collection literal. These three features are small, but they are used on almost every screen of a Flutter app.

The spread operator #

... unpacks one collection into another.

void main() {
  var fruits = ['apple', 'banana'];
  var vegetables = ['carrot', 'spinach'];

  var basket = ['bread', ...fruits, ...vegetables, 'milk'];
  print(basket);
}
[bread, apple, banana, carrot, spinach, milk]

Without the dots you would get a list inside a list.

It is also the simplest way to copy a list.

void main() {
  var original = [1, 2, 3];
  var copy = [...original];

  copy.add(4);
  print(original);
  print(copy);
}
[1, 2, 3]
[1, 2, 3, 4]

Spreading sets and maps #

void main() {
  var a = {1, 2, 3};
  var b = {3, 4};
  print({...a, ...b});

  var defaults = {'theme': 'light', 'fontSize': 14};
  var userSettings = {'theme': 'dark'};
  print({...defaults, ...userSettings}); // later keys win
}
{1, 2, 3, 4}
{theme: dark, fontSize: 14}

Null-aware spread #

If the collection might be null, use ...?. It adds nothing when the value is null.

void main() {
  List<String>? extras;

  var menu = ['tea', 'coffee', ...?extras];
  print(menu);
}
[tea, coffee]

Collection if #

Include an item only when a condition is true.

void main() {
  var isAdmin = false;
  var isLoggedIn = true;

  var menu = [
    'Home',
    if (isLoggedIn) 'Profile',
    if (isAdmin) 'Admin panel',
    if (isLoggedIn) 'Log out' else 'Log in',
  ];
  print(menu);
}
[Home, Profile, Log out]

Collection for #

Generate items with a loop, right inside the literal.

void main() {
  var numbers = [1, 2, 3];

  var squares = [for (final n in numbers) n * n];
  var labels = [for (var i = 1; i <= 3; i++) 'Item $i'];
  var lookup = {for (final n in numbers) n: 'number $n'};

  print(squares);
  print(labels);
  print(lookup);
}
[1, 4, 9]
[Item 1, Item 2, Item 3]
{1: number 1, 2: number 2, 3: number 3}

Combining them #

if and for can be nested, and a spread can follow either. This replaces a where plus a map.

void main() {
  var scores = {'Anu': 82, 'Bikash': 37, 'Chhiring': 94};
  var showHeader = true;

  var lines = [
    if (showHeader) ...['RESULTS', '-------'],
    for (final MapEntry(:key, :value) in scores.entries)
      if (value >= 40) '$key passed with $value',
  ];

  lines.forEach(print);
}
RESULTS
-------
Anu passed with 82
Chhiring passed with 94

Why Flutter developers love this #

A Flutter screen is a tree of nested lists. Being able to write “show this widget only if the user is logged in” inline keeps the layout readable.

children: [
  Header(),
  if (user != null) Avatar(user),
  for (final post in posts) PostCard(post),
]

Try it yourself #

You have var base = ['rice', 'dal'];, a nullable List<String>? sides and a bool wantsDessert. Build one list literal that contains the base items, the sides if there are any, and 'kheer' only when dessert is wanted.

Practise in the playground Updated by Santosh Adhikari