RayCC
Cover Image

Dart 3.6 cheat sheet

15 mins

Dart Programming Language Study Cheatsheet

Table of Contents

Style


Naming

_: Unused callback parameter.

Boolean variable name

No lines longer than 80 letters.

Import Order

  1. import "dart: ";
  2. import "package: ";
  3. import "my_dart.dart";

Comments

In terminal, run dart doc or dart format.

Read like a sentence.

Use /// for documents.

/// Short summary

///

/// Long description

/// Long description

/// Long description

class myClass{

Null

Do not initialize [null].

Do

var? foo;

if(foo)

if(nullableBool ?? false)

Don’t

var? foo = null;

if(foo == true)

if(nullableBool)

Collection

Use .isEmpty, not .length == 0;

Do not use .forEach(Callback).

Class

Use final for inner variable.

Use => for simple code.

Use var when type is long.

This

Tear off

Do

.map(print)

.map(MyClass.new) // Unnamed constructor.

.map(MyClass.myConstructor) // Named constructor.

Don’t

.map((x) => print(x))

.map((x) => MyClass(x))

.map((x) => MyClass.myConstructor(x))

Async

Use async when


Type


String Methods

.contain(X) .startsWith(X) .endsWith(X) .indexOf(X)

.toUpperCase() .toLowerCase()

.isEmpty .isNotEmpty

.substring(StartIndex, EndIndex) .split(X) .trim()

.replaceAll(Which, ToWhat)


Operator


~/ : Integer division

10 ~/ 3 = 3

++ -- ==

is

X is T

as

X as T

&& || !

Condition ? Expr1 : Expr2

??=

a = a ?? b

if(a == null) { a = b } else { a = a }

.. : Cascade

1
2
3
var paint = Pain()
  ..color = Colors.black // paint.color = Colors.black;
  ..strokeCap = StrokeCap.round; // paint.strokeCap = StrokeCap.round;

... : Spread

var newList = [0, 1, ...myList];

? : Can be null

int? x; // x can be null

foo?.bar // foo can be null

! : Can not be null

int! x; // x can not be null

foo!.bar // foo can not be null


Declaration


Import

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import "dart:async";
import "dart:io";

import "package:web/web.dart";

import "/dart/my_dart.dart" as my_dart;

import "my_dart.dart" show foo; // Import foo only.
import "my_dart.dart" hide foo; // Import except foo.
import "my_dart.dart" deferred; // Lazy loading.

Types

1
2
3
4
5
6
var hi = "hello"; // Can't change type.
dynamic ww = "world"; // Can change type.
Object ww2 = "world2"; // Can change type.

final String smile = ":)"; // Can only be assign a value Once.
const double pi = 3.15; // Can't change data.
1
2
3
4
String name = "Dart";
int createDate = 20250118;
double version = 1.0;
bool wip = false;
1
2
3
4
5
6
7
8
9
num updateDate = 2025_02_25;  // 20250225
int longNum = 1_000_000_000_000;  // 1000000000000

String longStr = """
Wrap 3 quotes.
""";
String longStr2 = "hello"
    "world"; // helloworld
RegExp myRegExp = RegExp(r"Dart");
1
2
3
4
String? iAmNull;
String? nullOk = null;
String ifNull = nullOk ?? "I'm not null";
// If [nullOk] is [null] then [ifNull] = "I'm not null".

List

1
List<int> myList = [1, 2, 3, ]; // myList[2] == 1

List Methods

Edit original

Return int

Return bool

Return Iterable (Need .toList())

Return 1 value

If method’s postfix is [At], then parameter is index.

If method’s postfix is [Where], then parameter is function.

Map

1
2
3
4
5
Map<int, String> myMap = {
  1: "one",
  2: "two",
  3: "three",
}; // myMap[1] == "one"

Map Methods

Edit Original

Return int

Return bool

Return nothing(void)

Return Iterable

Return 1 value

Make new Map

Set

1
2
3
4
5
Set<String> mySet = {
  "one",
  "two",
  "three",
};

Set Methods

Edit original

Return int

Return bool

Return nothing(void)

Return new Set

Enum

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
enum PlanetType { terrestrial, gas, ice }

enum Planet {
  mercury(planetType: PlanetType.terrestrial, moons: 0, hasRings: false),
  venus(planetType: PlanetType.terrestrial, moons: 0, hasRings: false),
  earth(planetType: PlanetType.terrestrial, moons: 1, hasRings: false);

  const Planet(
      {required this.planetType,
      required this.moons,
      required this.hasRings}); // Every [enum] constructor is [const].

  final PlanetType planetType; // Every [enum] variable is [final].
  final int moons;
  final bool hasRings;

  bool get isGiant =>
      planetType == PlanetType.ice || planetType == PlanetType.gas;
}

void aboutEnum() {
  final yourPlanet = Planet.earth;

  if (!yourPlanet.isGiant) {
    print('Your planet is not a "giant planet".');
  }
}

Basic


Main

1
2
3
4
5
6
7
void main() {
  print("hello world!");
  print("$hi ${ww + "!"}"); // hello world!

  print(myList[0]); // 1
  print(myMap[1]); // one
}
1
2
3
if (true) {
} else if (false) {
} else {}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
switch (createDate) {
  case 1:
  case 2:
  default:
}
// Do not need [break;] in every case.

String mySwitch = switch (name) {
  "Dart" => "YEAH!",
  "dart" => "yeah",
  _ => "???", // Underscore is default.
};

bool mySwitch2 = switch (name) {
  "Dart" || "dart" => true,
  _ => false,
};

switch (myList) {
  case [int a, int b]:
    print("[myList] has 2 int: $a,? $b");
  case [1, _, _] when myList.last == 3: 
    // Pattern matching, Guard clause.
    print("[myList] starts with 1, ends with 3");
  default:
}
1
2
3
4
5
6
7
8
for (int i = 0; i < 3; i++) {}

for (int num in myList) {}

while (false) {}

do {} while (false);
// [break;], [continue;]
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
try {
  throw Exception("Throw exception");
  // throw "Throw arbitrary object";
  // Choose one of the two lines above.
} on FormatException {
} on IOException catch (e) {
} catch (e) {
  // Avoid using without [on].
  if (false) rethrow;
} finally {
  // [finally] always run regardless of [try]-[catch].
  print("Do something after try-catch");
}

assert(true, "message");
// If [false], return [AssertionError] with ["message"].

Function

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
void myFunc1(int a, int b) {}
void myFunc2({required int a, required int b}) {} // Parameters have name.
void myFunc3(int a, [int b = 1]) {} // Default value.
void myFunc4(int a, {required int b, int c = 1}) {} // Name, default.
void myFunc5(int a, [int b = 1, int? c]) {} // [c] is optional.

/// Arrow function
///
/// Just 1 line
/// Do not need [return].
var myFunc7 = () => print("Arrow Func");
void myFunc8() => print("Shorthand syntax");

Typedef

1
2
3
4
5
6
7
typedef FuncTypedef = int Function(int a, int b);
typedef ListTypedef = List<int>;

FuncTypedef typedef1 = (int a, int b) {
  return a + b;
};
ListTypedef typedef2 = [1, 2, 3, ];

Class


Class

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
class MyClass {
  final String name; // Use final for inner value.

  // Constructor
  MyClass(this.name);
  // MyClass(String name) {this.name = name;}
  // MyClass(String name) : this.name = name;

  // Named constructor
  MyClass.noName() : name = "empty";
  MyClass.noName2() : this("empty");
  MyClass.nameWithAge(String name, int age) : name = "$name $age";
  MyClass.nameAndDoSomething() : name = "This is initialize" {
    print("Do something after initializing.");
  }

  void printName() {
    print("MyClass name is ${name}");
  }
}
1
2
3
4
var myInstance = MyClass("hello");
myInstance.printName();  // MyClass name is hello
var myInstance2 = MyClass.noName();
myInstance2.printName();  // MyClass name is empty

Private

Private class/variable/method name starts with _.

1
2
3
4
5
6
7
8
9
class _PrivateClass {
  final String _name;

  _PrivateClass(this._name);

  void _printName() {
    print("My PrivateClass name is ${_name}");
  }
}

Getter

1
2
3
4
5
6
7
8
class MyGetter {
  final double height;
  final double width;

  MyGetter(this.height, this.width);

  double get area => height * width;
}
1
2
var tmp = MyGetter(10, 30);
print(tmp.area);  // 300

Static

1
2
3
4
5
class MyStatic {
  static int count = 0;

  MyStatic() {}
}
1
print(MyStatic.count);  // 0

Inheritance

Can inheritance once.

Parents is super.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
class ChildClass extends MyClass {
  final int childInt;

  ChildClass(super.name, this.childInt);

  @override
  void printName() {
    print("This is child class.");
    super.printName();
  }
}

Class Modifier


instance: Can make instance.

extends: Inheritance. Only single extends.

implements: Multiple implements allowed.

with: Copy parent code and paste into child. Multiple with allowed.

instanceextendsimplementswith
classOOO
mixinXXOO
abstract classXOO
base classOOX
final classOXX
interface classOXO
sealed classXOO
sealed classXXX
abstract base classXOX
abstract interface classXXO
abstract final classXXX
mixin classOOOO
base mixin classOOXO
abstract mixin classXOOO
abstract base mixin classXOXO
base mixinXXXO

Mixin

Mixin can inheritance many times.

Mixin do not need super to call parent methods.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
mixin MyMixin {
  void mixinMethod() {
    print("This is mixin method");
  }

  void manyMixin() {
    print("This is mixin 1");
  }
}

mixin MyMixin2 {
  void manyMixin() {
    print("This is mixin 2");
  }
}

class ChildMixin with MyMixin, MyMixin2 {
  ChildMixin() {
    print("Mixin inheritance");

    mixinMethod(); // This is mixin method

    manyMixin(); // This is mixin 2
    // If multiple methods with same name, only last method executed.
  }
}

Abstract

Every abstract methods should be overrode.

In abstract class, this means child class.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
abstract class MyAbstract {
  final String name;

  MyAbstract(this.name);

  void printName(); // Abstract method.
  void whoAmI() {
    // If any codes are inside method,
    // then that method is not abstract anymore.
    print("I am not abstract method");
  }
}

class ChildAbstract extends MyAbstract {
  ChildAbstract(super.name);

  @override
  void printName() {
    print("Using abstract and override");
    super.tellName();
  }
}

Base

Child class should have [base], [final], [sealed].

1
2
3
base class MyBase {
  MyBase();
}

Final

1
2
3
final class MyFinal {
  MyFinal();
}

Interface

Every class is interface, so every class can use implements.

Interface can only has abstract methods.

1
2
3
interface class MyInterface {
  MyInterface();
}

Sealed

1
2
3
sealed class MySealed {
  MySealed();
}

Other Technic


DateTime

1
2
var now = DateTime.now();
var day = DateTime(2025, 1, 22); // Y: 2025, M: 1, D: 22

Generic

<T>: Any type var. T value.

<E>: Elements of list. List<E>

<K>: Keys. Map<K,V>

<V>: Values. Map<K,V>

1
2
3
4
5
6
class MyGeneric<T> {
    final T name;   

    MyGeneric({required this.name});
}
var temp = MyGeneric<int>(4);

Record: (a, b)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
(int, int) aboutRecord() {
  (String, int) person = ("Name", 30);
  print(person); // ("Name", 30)
  print(person.$1); // Name
  print(person.$2); // 30

  ({String name, int age}) human = (name: "Dart", age: 17);
  print(human); // (age: 17, name: Dart)
  print(human.name); // Dart

  return (1, 2);
}

var (num1, num2) = aboutRecord();
print(num1);  // 1
print(num2);  // 2

Destructuring

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
var [a, b] = ["b", "a"];
print(a + b); // ba
(a, b) = (b, a); // Swap.
print(a + b); // ab

final numbers = [1, 2, 3, 4, 5, ];
final [x, y, ..., z] = numbers;
print(x); // 1
print(z); // 5

final people = {
    "name": "Dart",
    "age": 17,
};
final {"name": hi, "age": count} = people;
print(hi); // Dart
print(count); // 17

Factory

Singleton pattern makes unique instance.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
class Singleton {
  static final Singleton _instance = Singleton._internal();

  // Factory constructor.
  factory Singleton() {
    return _instance;
  }

  // Real constructor is private.
  Singleton._internal();
}

Control-flow Operator

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
bool condition = false;

List<String> opListIf = [
  "one",
  "two",
  if (condition) "ten",
];

Map<String, int> opMapIf = {
  "one": 1,
  "two": 2,
  if (condition) "ten": 10,
};

Set<String> opSetIf = {
  "one", 
  "two", 
  if (condition) "ten",
};

List<int> opListFor = [0, for (int i = 1; i < 5; i++) i]; 
List<int> opListGenerate = List.generate(5, (index) => index);
// [0,1,2,3,4]

Operator Overriding

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Vector {
  final double x;
  final double y;

  Vector(this.x, this.y);

  Vector operator +(Vector v) => Vector(x + v.x, y + v.y);
  Vector operator -(Vector v) => Vector(x - v.x, y - v.y);

  @override
  bool operator ==(Object other) {
    return other is Vector && x == other.x && y == other.y;
  }

  // When override [==], should override [hasCode] too.
  @override
  int get hashCode => x.hashCode ^ y.hashCode;
  // Create new [hashCode] with [^](xor)

  // Override [toString] will change [print] output.
  @override
  String toString() {
    return "($x, $y)";
  }
}

final u = Vector(1, 2);
final v = Vector(48, 38);

print(u + v);  // (49, 40)
print(u - v);  // (-47, -36)

Call

call method can use instance like function.

1
2
3
4
5
6
class AboutCallMethod {
  void call(name) => print("Call: $name");
}

var myCall = AboutCallMethod();
myCall("hello"); // Call: hello

Async


import "dart:async";

Future - async

Future can handle 1 data.

1
2
3
4
5
Future<void> printWithDelay(String message) async {
  await Future.delayed(Duration(seconds: 1));
  print(message); 
  // Print message after 1 seconds.
}
1
2
3
4
5
Future<String> _readFileAsync(String filename) async {
  final file = File(filename);
  final contents = await file.readAsString();
  return contents.trim();
}

Stream - async*

Stream can handle many data.

yield: Return without break.

yield*: Yield [stream] type.

1
2
3
4
Stream<void> printWithDelay2(String message) async* {
  await Future.delayed(Duration(seconds: 1));
  yield "$message with delay 1 seconds";
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
Stream<int> sumStream(Stream<int> stream) async* {
  var sum = 0;
  await for (final value in stream) {
    yield sum += value;
  }
}

void sumCount() async {
  Stream<int> timerStream =
      Stream.periodic(Duration(seconds: 1), (count) => count);

  await for (final cumulative in sumStream(timerStream)) {
    print(cumulative);
  }
}

// 0, 1, 3, 6, 10, 15, 21, 28
// Print these values one at a time every second.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
void count() {
  // Number increase 1 per 1 seconds.
  Stream<int> numberStream =
    Stream.periodic(
      Duration(seconds: 1), 
      (count) => count,
    ).take(3);

  // Register listener, Start Stream.
  numberStream.listen(
    (data) => print('Received: $data'),
    onDone: () => print('Stream is done!'),
    onError: (error) => print('Error: $error'),
  );
}

// Received: 0
// Received: 1
// Received: 2
// Stream is done!

StreamController

Use stream manually.

.stream: Output.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
void streamController() {
  final controller = StreamController<int>();

  controller.stream.listen((data) => print('Received: $data'));

  for (int i = 0; i < 3; i++) {
    controller.sink.add(i); // Add data manually.
  }

  controller.close(); // Close manually.

  // Received: 0
  // Received: 1
  // Received: 2

  controller.stream
      .where((val) => val % 2 == 0)
      .listen((data) => print("even $data"));
  // Can use any methods between [.stream] and [.listen]..
  // This will be print "even 0", "even 2", ...
}

Isolate


import "dart:isolate";

Isolate.run(); // Run single code.

Isolate.spawn(); // Make new isolate.

https://dart.dev/language/isolates


Library