Dart Basics:
Dart is an open-source general-purpose programming language developed by
Google. It supports application development in both client and server-side. But it is
widely used for the development of android apps, iOS apps, IoT(Internet of
Things), and web applications using the Flutter Framework.
Introduction to Dart Programming Language
1. Variables, data types, and operators
2. Conditionals and loops
3. Collections
4. Functions
Variables, Comments and Data Types:
Variables hold the data that your program will work on.
To denote a variable with Dart, use the var keyword.
Add a new variable to main :
var myAge = 35;
Each Dart statement ends in a semicolon, just as statements do in C and Java. In the
code above, you’ve created a variable, myAge , and set it equal to 35.
You can use the built-in print in Dart to print the variable to the console. Add that
call after the variable:
print(myAge); // 35
Click RUN in DartPad to run the code. You’ll see the variable’s value, 35, prints in
the console.
VCS325-DART BASICS
Comments
Comments in Dart look just like those in C and in other languages: Text
following // is a single-line comment, while text within /* ... */ is a multi-line
comment block.
Here’s an example:
// 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.
*/
VCS325-DART BASICS
Data Types
Dart is statically typed, meaning that each variable in Dart has a type that
must be known when you compile the code. The variable type cannot change when
you run the program. C, Java, Swift and Kotlin are also statically typed.
If you don’t explicitly specify a data type, Dart uses type inference to try to
determine it, just like Swift and Kotlin do.
Dart also uses type inference for types other than int . Enter a variable, pi ,
equal to 3.14:
var pi = 3.14;
print(pi); // 3.14
VCS325-DART BASICS
Dart infers pi to be a double because you used a floating-point value to
initialize it. You can verify that in the Dart info panel by clicking pi .
Alternatively, instead of using type inference, you can declare the type.
Basic Dart Types
Dart uses the following basic types:
int: Integers
double: Floating-point numbers
bool: Booleans
String: Sequences of characters
Here’s an example of each Dart type:
VCS325-DART BASICS
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
The Dynamic Keyword
If you use the dynamic keyword instead of var , you get what’s effectively a
dynamically typed variable:
dynamic numberOfKittens;
VCS325-DART BASICS
Here, you can set numberOfKittens to a String using quotes.
numberOfKittens = 'There are no kittens!';
print(numberOfKittens); // There are no kittens!
numberOfKittens has a type, since Dart has static typing. But that type is dynamic ,
which means you can assign other values with other types to it. So you can assign
an int value below your print statement.
numberOfKittens = 0;
print(numberOfKittens); // 0
you could assign a double value:
numberOfKittens = 0.5;
print(numberOfKittens); // 0.5
VCS325-DART BASICS
Booleans
The bool type holds values of either true or false .
bool areThereKittens = false;
print(areThereKittens); // false
print(areThereKittens); // true
Operators
1. arithmetic
2. equality
3. increment and decrement
4. comparison
VCS325-DART BASICS
5. logical
Arithmetic Operators
print(40 + 2); // 42
print(44 - 2); // 42
print(21 * 2); // 42
print(84 / 2); // 42.0
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.
Equality Operators
Dart uses double-equals ( == ) equality and not-equals ( != ) operators:
print(42 == 43); // false
print(42 != 43); // true
VCS325-DART BASICS
Comparison Operators
Dart uses the typical comparison operators:
Less than (<)
Greater than (>)
Equal to (=>)
Here are some examples:
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
VCS325-DART BASICS
Logical Operators
Dart uses the same logical operators as other languages,
including && for AND and || for OR.
print((41 < 42) && (42 < 43)); // true
print((41 < 42) || (42 > 43)); // true
Strings
The Dart string type is String . Strings are expressed in Dart using text surrounded
by either single or double quotes.
You can use either var and type inference or String to create a string variable, like
other types you’ve seen:
var firstName = 'Albert';
String lastName = "Einstein";
you can embed the value of an expression inside a string by using the dollar sign
symbol: ${expression}.
If the expression is an identifier, you can omit the { }. Add the following:
VCS325-DART BASICS
var physicist = "$firstName $lastName likes the number ${84 / 2}";
print(physicist); // Albert Einstein
$firstName and $lastName are replaced by the variable values. The returns the
calculated result.
Escaping Strings
The escape sequences used in Dart are similar to those used in other C-like
languages. For example, you 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.
VCS325-DART BASICS
If you 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.
Here, Dart treated `\n` as normal text because the string started with r .
Click RUN in DartPad to see all your strings in the console.
Immutability
Dart uses the keywords const and final for values that don’t change.
VCS325-DART BASICS
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.
You can use const and final in place of var and let type inference determine the
type:
const speedOfLight = 299792458;
print(speedOfLight); // 299792458
Here, Dart infers that speedOfLight is an int , as you can see in DartPad’s info
panel.
final indicates that a variable is immutable, meaning you can’t
reassign final values. You can explicitly state the type with either final or const :
final planet = 'Jupiter';
VCS325-DART BASICS
// planet = 'Mars';
// error: planet can only be set once
final String moon = 'Europa';
print('$planet has a moon, $moon');
// Jupiter has a moon, Europa
Nullability
String? middleName = null;
print(middleName); // null
The default for a nullable type is null , so you can simplify the expression to the
following:
String? middleName;
VCS325-DART BASICS
print(middleName); // null
Run that and null prints to the console.
Control Flow
Control flow lets you dictate when to execute, skip over or repeat certain lines of
code. You use conditionals and loops to handle control flow in Dart.
In this section, you’ll learn more about:
Conditionals
While Loops
Continue and Break
For Loops
Here’s what you need to know about control flow elements in Dart.
Conditionals
VCS325-DART BASICS
The most basic form of control flow is deciding whether to execute or skip over
certain parts of your code, depending on conditions that occur as your program runs.
The language construct for handling conditions is the if / else statement. if / else in
Dart looks nearly identical to its use in other C-like languages.
If Statements
Suppose you have a variable, animal , that’s currently a fox. It looks like this:
var animal = 'fox';
You can use an if statement to check whether animal is a cat or a dog, then run
some corresponding code.
if (animal == 'cat' || animal == 'dog') {
print('Animal is a house pet.');
Here, you’ve used the equality and OR operators to create a bool inside the
condition for the if statement.
VCS325-DART BASICS
Else Statements
With an else clause, you can run alternative code if the condition is false:
else {
print('Animal is NOT a house pet.');
// Animal is NOT a house pet.
You can also combine multiple if / else statements into an if / else if / else construct:
if (animal == 'cat' || animal == 'dog') {
print('Animal is a house pet.');
} else if (animal == 'rhino') {
print('That\'s a big animal.');
} else {
print('Animal is NOT a house pet.');
// Animal is NOT a house pet.
You can have as many else if branches between if and else as you need.
While Loops
VCS325-DART BASICS
Loops let you repeat code a certain number of times or based on certain conditions.
You handle condition-based repetition using while loops.
There are two forms of while loops in Dart: while and do-while . The difference is
that for while , the loop condition occurs before the code block. In do-while , the
condition occurs after. That means that do-while loops ensure the code block runs at
least one time.
Testing the While Loop
To try this out, create a variable i initialized to 1:
var i = 1;
Next, use a while loop to print i while incrementing it. Set the condition to i is less
than 10:
while (i < 10) {
print(i);
i++;
// 1
// 2
// 3
// 4
// 5
VCS325-DART BASICS
// 6
// 7
// 8
// 9
Run the code and you’ll see that the while loop prints the numbers 1 to 9.
Trying Out the Do-While Loop
Reset i in DartPad, then add a do-while loop:
i = 1;
do {
print(i);
i++;
} while (i < 10);
// 1
// 2
// 3
// 4
// 5
// 6
VCS325-DART BASICS
// 7
// 8
// 9
The results are the same as before. This time, however, the loop body ran once
before checking the loop exit condition.
Continue and Break
Dart uses continue and break keywords in loops and elsewhere. Here’s what they
do:
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.
Be careful when using continue in your code. For example, if you take the do-
while loop from above, and you want to continue when i equals 5, that could result
in an infinite loop depending on where you place the continue statement:
i = 1;
do {
print(i);
if (i == 5) {
continue;
++i;
VCS325-DART BASICS
} while (i < 10);
// 1
// 2
// 3
// 4
// 5
// 5
// 5
// 5
// 5
// 5
// 5
// 5
// 5
// 5
// ...
The infinite loop occurs because, once i is 5, you never increment it again, so the
condition always stays true.
If you run this in DartPad, the infinite loop will cause the browser to hang. Instead,
use break , so the loop ends after i reaches 5:
VCS325-DART BASICS
i = 1;
do {
print(i);
if (i == 5) {
break;
++i;
} while (i < 10);
// 1
// 2
// 3
// 4
// 5
Run the code. Now, the loop ends after five iterations.
For Loops
In Dart, you use for loops to loop a predetermined number of times. for loops
consist of initialization, a loop condition and an action. Once again, they’re similar
to for loops in other languages.
Dart also offers a for-in loop, which iterates over a collection of objects. You’ll
learn more about these later.
VCS325-DART BASICS
To see how a for loop works, create a variable for the sum:
var sum = 0;
Next, use a for loop to initialize a loop counter from i to 1. You’ll then check
that i is less than or equal to 10 and increment i after every loop.
Inside the loop, use a compound assignment to add i to the running sum:
for (var i = 1; i <= 10; i++)
sum += i;
print("The sum is $sum"); // The sum is 55
Run your code in DartPad to see the sum.
Control Flow
VCS325-DART BASICS
Conditionals
While Loops
Continue and Break
For Loops
Conditionals
The most basic form of control flow is deciding whether to execute or skip over
certain parts of your code, depending on conditions that occur as your program runs.
If Statements
if (animal == 'cat' || animal == 'dog') {
print('Animal is a house pet.');
Here, you’ve used the equality and OR operators to create a bool inside the
condition for the if statement.
Else Statements
With an else clause, you can run alternative code if the condition is false:
else {
print('Animal is NOT a house pet.');
VCS325-DART BASICS
// Animal is NOT a house pet.
You can also combine multiple if / else statements into an if / else if / else construct:
if (animal == 'cat' || animal == 'dog') {
print('Animal is a house pet.');
} else if (animal == 'rhino') {
print('That\'s a big animal.');
} else {
print('Animal is NOT a house pet.');
// Animal is NOT a house pet.
You can have as many else if branches between if and else as you need.
While Loops
You handle condition-based repetition using while loops.
There are two forms of while loops in Dart: while and do-while . The difference is
that for while , the loop condition occurs before the code block. In do-while , the
condition occurs after. That means that do-while loops ensure the code block runs at
least one time.
VCS325-DART BASICS
Testing the While Loop
while (i < 10) {
print(i);
i++;
// 1
// 2
// 3
// 4
// 5
// 6
// 7
// 8
// 9
Trying Out the Do-While Loop
i = 1;
do {
print(i);
VCS325-DART BASICS
i++;
} while (i < 10);
// 1
// 2
// 3
// 4
// 5
// 6
// 7
// 8
// 9
Continue and Break
Dart uses continue and break keywords in loops and elsewhere. Here’s what they
do:
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.
i = 1;
do {
VCS325-DART BASICS
print(i);
if (i == 5) {
continue;
++i;
} while (i < 10);
// 1
// 2
// 3
// 4
// 5
// 5
// 5
// 5
// 5
// 5
// 5
// 5
// 5
VCS325-DART BASICS
// 5
// ...
The infinite loop occurs because, once i is 5, you never increment it again, so the
condition always stays true.
If you run this in DartPad, the infinite loop will cause the browser to hang. Instead,
use break , so the loop ends after i reaches 5:
i = 1;
do {
print(i);
if (i == 5) {
break;
++i;
} while (i < 10);
// 1
// 2
// 3
// 4
// 5
VCS325-DART BASICS
Run the code. Now, the loop ends after five iterations.
For Loops
for (var i = 1; i <= 10; i++) {
sum += i;
print("The sum is $sum"); // The sum is 55
Collections
Collections are useful for grouping related data. Dart includes several different types
of collections, but this tutorial will cover the two most common
ones: List and Map .
Lists
Lists in Dart are similar to arrays in other languages. You use them to maintain an
ordered list of values. Lists are zero-based, so the first item in the list is at index 0:
VCS325-DART BASICS
Here’s a list of different desserts:
List desserts = ['cookies', 'cupcakes', 'donuts', 'pie'];
You enclose the elements of a list in square brackets: [ ] . You use commas to
separate the elements.
At the beginning of the line, you can see that the type is List . You’ll notice there is
no type included. Dart infers that list has type List .
Here’s a list of integers:
final numbers = [42, -1, 299792458, 100];
Click numbers in DartPad and you’ll see that Dart recognizes the type as
a List of int .
VCS325-DART BASICS
Working With List Elements
To access the elements of a list, use subscript notation by putting the index number
between square brackets after the list variable name. For example:
final firstDessert = desserts[0];
print(firstDessert); // cookies
Since list indices are zero-based, desserts[0] is the first element of the list.
Add and remove elements with add and remove respectively:
desserts.add('cake');
print(desserts);
// [cookies, cupcakes, donuts, pie, cake]
desserts.remove('donuts');
print(desserts);
// [cookies, cupcakes, pie, cake]
Run the code to see the results.
VCS325-DART BASICS
Earlier, you learned about for loops. Dart’s for-in loop that works especially well
with lists. Try it out:
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.
You don’t need to use an index. Dart just loops through every element
of desserts and assigns it each time to a variable named dessert .
Getting hungry? Well, you can’t have any dessert until you’ve finished your
vegetables. :]
Maps
VCS325-DART BASICS
When you want a list of paired values, Map is a good choice. Dart Map s are similar
to dictionaries in Swift and maps in Kotlin.
Here’s an example of a map in Dart:
Map<String, int> calories = {
'cake': 500,
'donuts': 150,
'cookies': 100,
};
You surround Map s with curly braces { } . Use commas to separate a map’s
elements.
Elements of a map are called key-value pairs, where the key is on the left of a colon
and the value is on the right.
You find a value by using the key to look it up, like this:
final donutCalories = calories['donuts'];
print(donutCalories); // 150
VCS325-DART BASICS
The key, 'donuts' , is inside the square brackets after the map name. In this case, it
maps to a value of 150 .
Click donutCalories in DartPad and you’ll see that the inferred type is int? rather
than int . That’s because, if a map doesn’t contain the key that you’re looking up,
it’ll return a null value.
Add a new element to a map by specifying the key and assigning it a value:
calories['brownieFudgeSundae'] = 1346;
print(calories);
// {cake: 500, donuts: 150, cookies: 100, brownieFudgeSundae: 1346}
Run that code and you’ll see the map printed in horizontal format with your new
dessert at the end.
Functions
Functions let you package multiple related lines of code into a single body. You then
summon the function to avoid repeating those lines of code throughout your Dart
app.
VCS325-DART BASICS
A function consists of the following elements:
Return type
Function name
Parameter list in parentheses
Function body enclosed in brackets
Defining Functions
The code you’re turning into a function goes inside the curly brackets. When you
call the function, you pass in arguments that match the types of the parameters of
the function.
Next, you’ll write a new function in DartPad that will check to see if a given string
is banana:
bool isBanana(String fruit) {
return fruit == 'banana';
The function uses return to return a bool . The argument you pass to the function
determines the bool .
VCS325-DART BASICS
This function will always return the same value type for any given input. If a
function doesn’t need to return a value, you can set the return type
to void . main does this, for example.
Working With Functions
You can call the function by passing in a string. You might then pass the result of
that call to print :
void main() {
var fruit = 'apple';
print(isBanana(fruit)); // false
Nesting Functions
Typically, you define functions either outside other functions or inside Dart classes.
However, you can also nest Dart functions. For example, you can
nest isBanana inside main .
void main() {
bool isBanana(String fruit) {
return fruit == 'banana';
var fruit = 'apple';
VCS325-DART BASICS
print(isBanana(fruit)); // false
You can also change the argument you to a function, then call it again with the new
argument:
fruit = 'banana';
print(isBanana(fruit)); // true
The result of calling the function depends entirely on the arguments you pass in.
Optional Parameters
If a parameter to a function is optional, you can surround it with square brackets and
make the type nullable:
String fullName(String first, String last, [String? title]) {
if (title == null) {
return '$first $last';
} else {
return '$title $first $last';
In this function, title is optional. It will default to null if you don’t specify it.
VCS325-DART BASICS
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 and Default Values
When you have multiple parameters, it can be confusing to remember which is
which. Dart solves this problem with 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.
With named parameters, you can pass in arguments in a different order by supplying
the parameter names with a colon:
print(withinTolerance(min: 1, max: 5, value: 11)); // false
VCS325-DART BASICS
You can leave off the parameters with default values when calling the function.
print(withinTolerance(value: 5)); // true
Run your code to see your new functions in action.
Anonymous Functions
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.
To pass these functions around as values, omit the function name and return type.
Since there’s no name, this type of function is called an anonymous function.
You can assign an anonymous function to a variable named onPressed , like so:
final onPressed = () {
VCS325-DART BASICS
print('button pressed');
};
onPressed has a value of type Function . The empty parentheses indicate the
function has no parameters. Like regular functions, the code inside the curly brackets
is the function body.
To execute the code within the function body, call the variable name as if it were the
name of the function:
onPressed(); // button pressed
You 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 => .
Here’s a comparison of the anonymous function above and a refactored version:
// original anonymous function
final onPressed = () {
print('button pressed');
};
// refactored
final onPressed = () => print('button pressed');
That’s much nicer to read.
VCS325-DART BASICS
Using Anonymous Functions
You’ll often see anonymous functions in Flutter, like those above, passed around as
callbacks for UI events. This lets you specify the code that runs when a user does
something, like pressing a button.
Another common place where you’ll see anonymous functions is with collections.
You can give a collection an anonymous function that will perform some task on
each element of the collection. For example:
// 1
final drinks = ['water', 'juice', 'milk'];
// 2
final bigDrinks = drinks.map(
// 3
(drink) => drink.toUpperCase()
);
// 4
print(bigDrinks); // (WATER, JUICE, MILK)
Let’s look at each step:
1. Define a list of drinks that have lowercase letters.
2. .map takes all the list values and returns a new collection with them.
3. An anonymous function is passed as a parameter. In that anonymous function,
you have a drink argument that represents each element of the list.
4. The body of the anonymous function converts each element to uppercase and
returns the value. Since the original list is a list of strings, drink also has
type String .
VCS325-DART BASICS
Using an anonymous function and combining it with .map is a convenient way to
transform one collection into another.
Note: Don’t confuse the .map method with the Map type.
Run the code to see the resulting collection.
VCS325-DART BASICS