A new way of learning Dart language. Don't just read but try it out yourself.

A cheat class to learn the Dart programming language for Flutter enthusiasts.
For best experience, use PC / Laptop.

The embedded editors in this codelab have partially completed code snippets. You can use these editors to test your knowledge by completing the code and clicking the Run button. To run the code formatter (dartfmt), click Format. The Reset button erases your work and restores the editor to its original state.

1. Hello Flutter

This is our first program. Let's see how we can print "Hello, World Flutter". Try changing it to your name and then click on the Run button. For eg: Hello Pawan

main() is the execution point. This is the point from where your code starts.
void main() {
  print('Hello, Flutter');
}

Wow, nice start. You just printed your name in the console 🥳.


2. Functions

Function is nothing but a piece of code which does something. For eg: When you say call someone then we can use a function named call() and write some code inside it to make it work.

Dart is a true object-oriented language, so even functions are objects and have a type, Function. This means that functions can be assigned to variables or passed as arguments to other functions. You can also call an instance of a Dart class as if it were a function.

A basic Dart program

// Define a function.
void printInteger(int aNumber) {
  print('The number is $aNumber.'); // Print to console.
}

// This is where the app starts executing.
void main() {
  var number = 42; // Declare and initialize a variable.
  printInteger(number); // Call a function.
}

Here’s what this program uses that applies to all (or almost all) Dart apps:

// This is a comment.

A single-line comment. Dart also supports multi-line and document comments.  

void

A special type that indicates a value that’s never used.

Functions like printInteger() and main() that don’t explicitly return a value have the void return type.

int

Another type, indicating an integer. Some additional built-in types are String, List, and bool.

42

A number literal. Number literals are a kind of compile-time constant.

print()

A handy way to display output.'...' (or "...")A string literal.

$variableName (or ${expression})

String interpolation: including a variable or expression’s string equivalent inside of a string literal.

main()

The special, required, top-level function where app execution starts.

var

A way to declare a variable without specifying its type.

Now change the function name to "showANumber()" and print "The lottery number is 25" and then Run it.

// Define a function.
void printInteger(int aNumber) {
  print('The number is $aNumber.'); // Print to console.
}

// This is where the app starts executing.
void main() {
  var number = 42; // Declare and initialize a variable.
  printInteger(number); // Call a function.
}

3. Variables

Variable is something which holds a value and that value can change or vary. So that's why it is called a variable.

For eg: var name = "Pawan";

Variables store references. The variable called name contains a reference to a String object with a value of “Pawan”. The type of the name variable is inferred to be String, but you can change that type by specifying it. If an object isn’t restricted to a single type, specify the Object or dynamic type

dynamic name = 'Pawan';

Another option is to explicitly declare the type that would be inferred:

String name = 'Pawan';

var can be of different types as mentioned below.

Built-in types

The Dart language has special support for the following types:

  • numbers
  • strings
  • booleans
  • lists (also known as arrays)
  • sets
  • maps
  • runes (for expressing Unicode characters in a string)
  • symbols

Try changing my values with yours like your name, height, gender and country etc, And Run it.

void main() {
	
  //This is for declaring a  number
  int age = 25; 
  
  //This is a string
  String name = 'Pawan Kumar'; 
  
  //This is boolean which can be true or false
  bool isMale = true; 
 
  //This is a double which holds floating value
  double height = 170.5;
  
  //Common variable when you don't want to specify it's type.
  var country = 'India';
  
  print(age);
  print(name);
  print(isMale);
  print(height);
  print(country);
  
}

Well done, you are learning it fast ⚡️.

Final and const

If you never want to change a variable, use final or const, either instead of var or in addition to a type.

A final variable can be set only once; a const variable is a compile-time constant. (Const variables are implicitly final.) A final top-level or class variable is initialized the first time it’s used.

The main difference between final and const is that a final object can be modified but a const can never.

Play with this program and follow the instruction to understand it better.

void main() { 

  //Final types
  
  // A constant value like math's pi
  const pi = 3.14; 
  
  // A final value which is not supposed to change like someone's gender
  final gender = 'Male'; 
  
  print(pi);
  print(gender);
  
  // But both have a minor difference which we can see below.
  
  // Try changing it from final to const & see if that works.
  final List myList = [1,2,3];
  print(myList[myList.length-1]);
  
  myList.add(10);
  
  print(myList[myList.length-1]);

  
}

When you tried const with myList, it showed an error right? That is actually expected because as I told you that const object cannot be modified.

4. Functions in detail

A function can have any number of required positional parameters. These can be followed either by named parameters or by optional positional parameters (but not both).

Named parameters

Named parameters are optional unless they’re specifically marked as required.

When calling a function, you can specify named parameters using paramName: value. For example:

enableAuthentication(touchID: true, faceID: false);

When defining a function, use {param1, param2, …} to specify named parameters:

/// Sets the [bold] and [hidden] flags ...
void enableAuthentication({bool touchID, bool faceID}) {...}
Although named parameters are a kind of optional parameter, you can annotate them with `@required` to indicate that the parameter is mandatory — that users must provide a value for the parameter.
const Scrollbar({Key key, @required Widget child})

//To use the @required annotation, depend on the meta package and import package:meta/meta.dart.

Optional positional parameters

Wrapping a set of function parameters in [] marks them as optional positional parameters:

void main(){
String say(String from, String msg, [String device]) {
  var result = '$from says $msg';
  if (device != null) {
    result = '$result with a $device';
  }
  return result;
}
}

Default parameter values

Your function can use = to define default values for both named and positional parameters. The default values must be compile-time constants. If no default value is provided, the default value is null.

Here’s an example of setting default values for named parameters:

/// Sets the [touchID] and [faceID] flags ...
void enableAuthentication({bool touchID = false, bool faceID = false}) {...}

// touchID will be true; faceID will be false.
enableAuthentication(touchID: true);

To understand functions in detail, try playing with this piece of code because until you practice, you won't understand it well. So it's very crucial to play with it.

Also, try to create a function which can tell you if a number is even or odd.
void main() {
  int num1 = 20;
  int num2 = 5;
  printNumber(num1, num2);

  //Call function 2 (We are looping the data here)
  var list = [1, 2, 3];
  list.forEach(printElement);

  //Call function 3
  var add2 = makeAdder(2); // Create a function that adds 2.
  var add4 = makeAdder(4); // Create a function that adds 4.
  assert(add2(3) == 5);
  assert(add4(3) == 7);
  
  //Call function 4
  var output1 = say("Pawan", "Hi");
  print(output1);
  
  var output2 = say("Pawan", "Hi", "Pixel");
  print(output2);
  
  //Call function 5
  var output3 = sayAgain("PK", msg : "Hello");
  print(output3);
  
}

//function 1
void printNumber(num number1, number2) {
  print(number1 + number2);
}

//function 2
printElement(element) {
  print(element);
}

//function 3
Function makeAdder(num n) {
  return (num i) => n + i;
}

//function 4
String say(String from, String msg, [String device]) {
  var result = '$from says $msg';
  if (device != null) {
    result = '$result with a $device';
  }
  return result;
}

//function 4
String sayAgain(String from, {String msg, String device = "Galaxy"}) {
  var result = '$from says $msg';
  if (device != null) {
    result = '$result with a $device';
  }
  return result;
}

The => expr syntax is a shorthand for { return expr; }. The => notation is sometimes referred to as arrow syntax.

Functions can also give back some value or another function and we call/represent with return keyword.

All functions return a value. If no return value is specified, the statement return null; is implicitly appended to the function body.

bool isDog(int legs) {
  return legs==4;
}

This function returns true if the legs are 4 otherwise it returns false

5. Operators

Dart supports the operators shown in the following table.

Let's take a look at some common ones.

Arithmetic Operators:

assert(2 + 3 == 5);
assert(2 - 3 == -1);
assert(2 * 3 == 6);
assert(5 / 2 == 2.5); // Result is a double
assert(5 ~/ 2 == 2); // Result is an int
assert(5 % 2 == 1); // Remainder

assert('5/2 = ${5 ~/ 2} r ${5 % 2}' == '5/2 = 2 r 1');

Type test operators


The as(Typecast),  is(True if the object has the specified type), and is! (False if the object has the specified type) operators are handy for checking types at runtime.

Example:

(emp as Person).firstName = 'Pawan';

if (emp is Person) {
  // Type check
  emp.firstName = 'Pawan';
}

Play with all the operators to learn more about them. Experimenting is important.



void main() {

  var z = 5;
  
  var a, b;

	//Play with prefix and postfix increment and decrement operators
    
    a = 0;
    b = ++a; // Increment a before b gets its value.
    assert(a == b); // 1 == 1

    a = 0;
    b = a++; // Increment a AFTER b gets its value.
    assert(a != b); // 1 != 0

    a = 0;
    b = --a; // Decrement a before b gets its value.
    assert(a == b); // -1 == -1

    a = 0;
    b = a--; // Decrement a AFTER b gets its value.
    assert(a != b); // -1 != 0
    
    
    //Play with Equality and relational operators
    
    assert(2 == 2);
	assert(2 != 3);
	assert(3 > 2);
	assert(2 < 3);
	assert(3 >= 3);
	assert(2 <= 3);
    
     // Assign value to a
	  a = value;
      
	 // Assign value to b if b is null; otherwise, b stays the same
	  b ??= value;
  
      print(z + z);
      print(z / z);
      print(z * z);
      print(z - z);
      print(z = z);
      print(z != z);
      print(z % z);
      print(z < z);
      print(z > z);
      print(z >= z);
      print(z <= z);
      print(z | z);
}

6. Controls

Conditional expressions

Dart has two operators that let you concisely evaluate expressions that might otherwise require if-else statements:

condition ? expr1 : expr2

If condition is true, evaluates expr1 (and returns its value); otherwise, evaluates and returns the value of expr2.

expr1 ?? expr2

If expr1 is non-null, returns its value; otherwise, evaluates and returns the value of expr2.

Example:

var title = isPublic ? 'public' : 'private';


// All of the below produces the same result

//Better version
String playerName(String name) => name ?? 'Guest';


// Slightly longer version uses ?: operator.
String playerName(String name) => name != null ? name : 'Guest';

// Very long version uses if-else statement.
String playerName(String name) {
  if (name != null) {
    return name;
  } else {
    return 'Guest';
  }
}

Cascade notation (..)

Cascades (..) allow you to make a sequence of operations on the same object.

Example:

Version 1

var button = querySelector('#confirm');
button.text = 'Confirm';
button.classes.add('important');
button.onClick.listen((e) => window.alert('Confirmed!'));

can be replaced with Version 2

querySelector('#confirm') // Get an object.
  ..text = 'Confirm' // Use its members.
  ..classes.add('important')
  ..onClick.listen((e) => window.alert('Confirmed!'));

Control flow statements

Control flow generally have some decision making involve. Below example can help you in understanding the control flow in dart.

Control flows are all about "WHICH" and "TILL WHEN".
//Control Flow

void main() {
  // if else
  bool hasChargerInTheBox = true;
  if (hasChargerInTheBox) {
    print('Non iPhone');
  } else {
    print('iPhone');
  }

//For loop
  var listData = [1, 2, 3, 4, 5];
  for (var x in listData) {
    print(x);
  }

//While and Do-While
  int number = 0;
  do {
    if (number % 2 == 0) {
      print(number);
    }
    number++;
  } while (number < 10);

 //Switch Case
  var command = 'OPEN';
  switch (command) {
    case 'CLOSED':
      print('Please open the ticket');
      break;
    case 'PENDING':
      print('Ticket will be opened soon');
      break;
    case 'OPEN':
      print('Ticket is already opened');
      break;
    case 'DENIED':
      print('You cannot open the ticket');
  }
}

7. Asserts

During development, use an assert statement — assert(condition, optionalMessage); — to disrupt normal execution if a boolean condition is false.

It can be used while developing. Although with the support of null-safety it won't be needed anymore.


void main() {
  String text = 'I hope you are enjoying codepur.';
  assert(text != null);
}

8. Exceptions

Your Dart code can throw and catch exceptions. Exceptions are errors indicating that something unexpected happened. If the exception isn’t caught, the isolate that raised the exception is suspended, and typically the isolate and its program are terminated.

Some of the examples can be tested here:


void main() {
  int x = 11;
  int y = 0;
  int res;
  try {
    res = x ~/ y;
  } on IntegerDivisionByZeroException {
    print('Cannot divide by zero');
  }
  exception();
  exceptionWithFinaly();
}

// Try catch with exception
exception() {
  int x = 10;
  int y = 0;
  int res;

  try {
    res = x ~/ y;
  } catch (e) {
    print(e);
  }
}

// With finally
exceptionWithFinally() {
  int x = 9;
  int y = 0;
  int res;

  try {
    res = x ~/ y;
  } on IntegerDivisionByZeroException {
    print('Cannot divide by zero');
  } finally {
    print('Finally block executed');
  }
}

9. Classes and Objects

Dart is an object-oriented language with classes and mixin-based inheritance. Every object is an instance of a class, and all classes descend from Object.

You can consider classes as a blueprint. And objects are made out of those blueprints.

// Structure of Class in Dart

 class className {
    <fields>
    <getters/setters>
    <constructors>
    <functions>
 }

Fields/Instance variables − A field is any variable declared in a class. Fields represent data pertaining to objects.

Setters and Getters − Allows the program to initialize and retrieve the values of the fields of a class. A default getter/ setter is associated with every class. However, the default ones can be overridden by explicitly defining a setter/ getter.

Constructors − responsible for allocating memory for the objects of the      class.

Methods − Methods represent actions an object can take. They are also at times referred to as functions.

void main() {
  Car c = Car();
  c.desciption();
}

class Car {
  // fields
  String engine = "B1001";
  String brand = "Ferari";
  String owner = "Zidniryi";
  int yearProd = 2021;
  bool isColorRed = true;

  // method
  void desciption() {
    print(engine);
    print(brand);
    print(owner);
    print(yearProd);
    print(isColorRed);
  }
}

10. Regex

A regular expression (regex or regexp for short) is

  • a special text string for describing a search pattern.
  • You can think of regular expressions as wildcards on steroids.

void main() {
  RegExp re = new RegExp(r'(\w+)');
  String str1 = "one two three";
  print('Has match: ${re.hasMatch(str1)}');
  // First match
  Match firstMatch = re.firstMatch(str1);
  print('First match: ${str1.substring(firstMatch.start, firstMatch.end)}');

  // Iterate all matches
  Iterable matches = re.allMatches(str1);
  matches.forEach((match) {
    print(str1.substring(match.start, match.end));
  });
}

11. Lists

Perhaps the most common collection in nearly every programming language is the array, or ordered group of objects. In Dart, arrays are List objects, so most people just call them lists.

void main() {
  // Using a List constructor.
  // Or simply use a list literal.
  var fruits = ['apples', 'oranges'];
  // Add to a list.
  fruits.add('kiwis');
  print(fruits);
  print(fruits.length);

  // Add multiple items to a list.
  fruits.addAll(['grapes', 'bananas']);
  print(fruits);

  // Get the list length.
  assert(fruits.length == 5);
  // Remove a single item.
  var appleIndex = fruits.indexOf('apples');
  fruits.removeAt(appleIndex);

  assert(fruits.length == 4);
  print(fruits);
  
  // Check with isEmpty or isNonEmpty rather than length
  assert(fruits.isEmpty == false);
  
  // Remove all elements from a list.
  fruits.clear();
  assert(fruits.length == 0);
  print(fruits);
}

12. Mixins

Mixins are a way of reusing a class’s code in multiple class hierarchies.

To use a mixin, use the with keyword followed by one or more mixin names. The following example shows two classes that use mixins:

class Musician extends Performer with Musical {
  // ···
}

class Maestro extends Person
    with Musical, Aggressive, Demented {
  Maestro(String maestroName) {
    name = maestroName;
    canConduct = true;
  }
}

13. Asynchronous Future

Dart libraries are full of functions that return Future or Stream objects. These functions are asynchronous: they return after setting up a possibly time-consuming operation (such as I/O), without waiting for that operation to complete.

The async and await keywords support asynchronous programming, letting you write asynchronous code that looks similar to synchronous code.

Future<void> getUser() {
  return Future.delayed(Duration(seconds: 3), () => print('User Data'));
}

void main() {
  getUser();
  print('Fetching user data...');
}

14. Synchronous

Consider a situation like standing in an ATM queue. Only one person can use the ATM at once. That's exactly what synchronous operation is. Others will wait while one task is getting executed.

import 'dart:io';

void main() {
  print("Enter your name :");

  // Prompt for user input
  String name = stdin.readLineSync();

  // This is a synchronous method that reads user input
  print("Hello ${name}");
  print("End of main");
}

15. Using Math Lib

We can many core libraries in our code. One of the common library is dart:math.

import "dart:math" as math;

void main() {
  print(math.pi / 3);
}
}

16. Create a lib

We can create above kind of libraries easily by ourselves.

// Create library
dart_lib(num1, num2) {
  print(num1 + num2);
}
// Calling the library
import 'dart_lib.dart';

void main() {
  // call that
  dart_lib(20, 20);
}

This playbook will keep updating as per latest changes and updates.

Take a full language tour here:

A tour of the Dart language
A tour of all of the major Dart language features.

Take a full core library tour here:

A tour of the core libraries
Learn about the major features in Dart’s libraries.

If you are a video person, then start your dart journey with the below video.

Enjoyed the post?

A clap is much appreciated if you enjoyed :)

Join the conversation

Table of Contents
Great! Next, complete checkout for full access to Codepur.
Welcome back! You've successfully signed in.
You've successfully subscribed to Codepur.
Success! Your account is fully activated, you now have access to all content.
Success! Your billing info has been updated.
Your billing was not updated.