Flutter is an exciting UI toolkit from Google that lets you write apps for different platforms including iOS, Android, the web and more, all using one codebase. Flutter uses the Dart language.
To get started quickly, use the open-source tool DartPad.
Can install the Dart SDK locally on a machine. One way to do so is to install the Flutter SDK as it will also install the Dart SDK.
To install the Dart SDK directly, visit https://dart.dev/get-dart.
Dart has many similarities to other languages such as Java, C#, Swift and Kotlin.
- Dart programs begin with a call to
main
.
void main() {
}
- Some core concepts:
- Variables, Comments and Data Types
- Basic Dart Types
- Operators
- Strings
- Immutability
- Nullability
- Condition and Break
- For Loops
Variables hold the data that your program will work on.
var myAge = 35;
Text following //
is a single-line comment, while text within /* ... */
is a multi-line comment block.
// This is a single-line comment.
print(myAge); // This is also a single-line comment.
/*
This is a multi-line comment block. This is useful for long
comments that span several lines.
*/
Dart is statically typed, meaning that each variable in Dart has a type that must be known when you compile the code. (contrasts with languages like Python and JavaScript, which are dynamically typed → variables can hold different kinds of data when running the program)
If you don't explicitly specify a data type, Dart uses type inference to try to determine it. For example of enter a variable, pi
, equal to 3.14 → Dart infers pi
to be a double
:
var pi = 3.14;
print(pi); // 3.14
- int: Integers
- double: Floating-point numbers
- bool: Booleans
- String: Sequences of characters
int
and double
both derive from a type named num
. num
uses the dynamic keyword to mimic dynamic typing in the statically typed Dart. Do this by replacing var with the type you want to use:
int yourAge = 27;
print(yourAge); // 27
If you use the dynamic
keyword instead of var
, you get what's effectively a dynamically typed variable:
dynamic numberOfKittens;
numberOfKittens = 'There are no kittens!';
print(numberOfKittens); // There are no kittens!
numberOfKittens = 0;
print(numberOfKittens); // 0
numberOfKittens = 0.5;
print(numberOfKittens); // 0.5
→ No error assigning different types.
The bool
type holds values of either true or false.
bool areThereKittens = false;
print(areThereKittens); // false
Can embed the value of an expression inside a string by using the dollar sign symbol: ${expression}.
var physicist = "$firstName $lastName likes the number ${84 / 2}";
print(physicist); // Albert Einstein
Use \n
for a new line. If there are special characters in the string, use \
to escape them:
var quote = 'If you can\'t explain it simply\nyou don\'t understand it well enough.';
print(quote);
// If you can't explain it simply
// you don't understand it well enough.
If need to show escape sequences within the string, you can use raw strings, which are prefixed by r.
var rawString = r"If you can't explain it simply\nyou don't understand it well enough.";
print(rawString);
// If you can't explain it simply\nyou don't understand it well enough.
Some examples of Dart's operators include:
- arithmetic
- equality
- increment and decrement
- comparison
- logical
For division, even with integers, Dart infers the resulting variable to be a double. That's why you get 42.0 instead of 42 for the last print statement.
print(40 + 2); // 42
print(44 - 2); // 42
print(21 * 2); // 42
print(84 / 2); // 42.0
print(42 == 43); // false
print(42 != 43); // true
print(42 < 43); // true print(42 >= 43); // false
In addition, it also uses the usual compound arithmetic/assignment operators:
var value = 42.0;
value += 1; print(value); // 43.0
value -= 1; print(value); // 42.0
value *= 2; print(value); // 84.0
value /= 2; print(value); // 42.0
A shortened form of += 1
is ++
:
value++;
print(value); // 43.0
Has the usual modulo operator (%) to return the remainder after one number has been divided by another:
print(392 % 50); // 42
&&
for AND and ||
for OR.
print((41 < 42) && (42 < 43)); // true
print((41 < 42) || (42 > 43)); // true
The negation operator is the exclamation mark, which turns false to true and true to false.
print(!(41 < 42)); // false
The double-question-mark operator, ??
, is like the Elvis operator in Kotlin: It returns the left-hand operand if the object isn't null. Otherwise, it returns the right-hand value:
String? middleName;
var name = middleName ?? 'none';
print(name); // none
The ?.
operator returns null if the object itself is null. Otherwise, it returns the value of the property on the right-hand side:
print(middleName?.length); // null
Dart uses the keywords const
and final
for values that don't change:
- Use
const
for values that are known at compile-time. - Use
final
for values that don't have to be known at compile-time but cannot be reassigned after being initialized.
Can use const
and final
in place of var
and let type inference determine the type.
To tell Dart that you want to allow the value null
, add ?
after the type.
String? middleName = null;
print(middleName); // null
Let you dictate when to execute, skip over or repeat certain lines of code:
- Conditionals
- While Loops
- Continue and Break
- For Loops
Simple if/else
statements.
Two forms of while loops in Dart: while
and do-while
.
i = 1;
do {
print(i);
i++;
} while (i < 10);
// 1
// 2
// 3
// 4
// 5
// 6
// 7
// 8
// 9
- continue: Skips remaining code inside a loop and immediately goes to the next iteration.
- break: Stops the loop and continues execution after the body of the loop.
Dart also offers a for-in
loop, which iterates over a collection of objects.
for (final dessert in desserts) {
print('I love to eat $dessert.');
}
// I love to eat cookies.
// I love to eat cupcakes.
// I love to eat pie.
// I love to eat cake.
Dart includes several different types of collections, but the two most common ones are: List
and Map
.
List desserts = ['cookies', 'cupcakes', 'donuts', 'pie'];
Map<String, int> calories = {
'cake': 500,
'donuts': 150,
'cookies': 100,
};
- Return type
- Function name
- Parameter list in parentheses
- Function body enclosed in brackets
bool isBanana(String fruit) {
return fruit == 'banana';
}
void main() {
bool isBanana(String fruit) {
return fruit == 'banana';
}
var fruit = 'apple';
print(isBanana(fruit)); // false
}
String fullName(String first, String last, [String? title]) {
if (title == null) {
return '$first $last';
} else {
return '$title $first $last';
}
}
Now, you can call the function with or without the optional parameter:
print(fullName('Joe', 'Howard'));
// Joe Howard
print(fullName('Albert', 'Einstein', 'Professor'));
// Professor Albert Einstein
named parameters, which you get by surrounding the parameter list with curly brackets: { }
. These parameters are optional by default, but you can give them default values or make them required by using the required keyword:
bool withinTolerance({required int value, int min = 0, int max = 10}) {
return min <= value && value <= max;
}
→ value
is required, while min
and max
are optional with default values.
Dart supports first-class functions, meaning that it treats functions like any other data type. You can assign them to variables, pass them as arguments and return them from other functions.
Can simplify functions whose body only contains a single line by using arrow syntax. To do this, remove the curly brackets and add a fat arrow =>
.
// original anonymous function
final onPressed = () {
print('button pressed');
};
// refactored
final onPressed = () => print('button pressed');
You'll often see anonymous functions when:
- passed around as callbacks for UI events.
- with collections.
// 1
final drinks = ['water', 'juice', 'milk'];
// 2
final bigDrinks = drinks.map(
// 3
(drink) => drink.toUpperCase()
);
// 4
print(bigDrinks); // (WATER, JUICE, MILK)