DART: Introduction to Dart

Dart is the statically typed, object-oriented programming language that powers Flutter. Designed by Google for building fast, expressive applications, Dart compiles to both native machine code and JavaScript. Understanding Dart's compilation model, memory management, and concurrency primitives is essential before writing serious Flutter applications.

Dart is more than just "Flutter's language." It is a carefully designed language with a clear purpose: making it easy to write expressive, high-performance applications for any platform. Before diving into widgets and UI patterns, building a solid understanding of Dart itself pays dividends in every Flutter project you ever write.


What Is Dart?

Dart is a statically typed, compiled, object-oriented programming language developed by Google. It was designed specifically for building user interfaces, but has grown into a general-purpose language targeting mobile, web, server, and desktop.

Key characteristics:

  • Statically typed — variable types are known at compile time, catching errors early
  • Object-oriented — everything is an object, including numbers and functions
  • Garbage collected — memory is managed automatically
  • Async-first — built-in Future, Stream, async, and await primitives
  • C-like syntax — familiar to developers coming from Java, C#, or JavaScript

Getting Started

Install the SDK

Download Dart from the official site:

bash
# macOS via Homebrew
brew tap dart-lang/dart
brew install dart

# Verify installation
dart --version

Online Editor

For quick experiments without installing anything, use DartPad at dartpad.dev — a browser-based Dart editor with instant execution.


Basic Syntax

Dart uses C-style syntax. Every Dart program starts from the main() function.

dart
void main() {
  var firstName = 'Amr';
  String lastName = 'Tarek';
  print(firstName + ' ' + lastName); // Amr Tarek
}

Comments

dart
// Single-line comment

/*
  Multi-line
  comment
*/

/// Documentation comment (appears in generated docs)
/// [parameter] describes a parameter


The Dart Virtual Machine (Dart VM)

The Dart VM is the runtime that executes Dart programs. It operates in two phases:

md
Dart VM Execution
------------------
Source Code (.dart)
       |
       v
[Compile Time]
  - Parse and type-check
  - Optimize
  - Early error detection
       |
       v
[Runtime]
  - Execute compiled code
  - Manage memory allocation
  - Handle dynamic operations
  - Process user interactions

At compile time, Dart code is checked and optimized, ensuring early detection of type errors, unused variables, and other issues.

At runtime, the Dart VM executes the compiled code, managing dynamic operations such as memory allocation and user interactions.


Dart Compilation: AOT and JIT

Dart uses two compilation strategies — one for development speed and one for production performance.

md
+------------------------+        +------------------------+
|   JIT Compilation      |        |   AOT Compilation      |
|   (Development)        |        |   (Production)         |
|                        |        |                        |
|  Compiles at runtime   |        |  Compiles before run   |
|  Enables hot reload    |        |  Faster app startup    |
|  Fast iteration cycle  |        |  Optimized performance |
|  Includes debug info   |        |  Smaller runtime       |
+------------------------+        +------------------------+

JIT (Just-In-Time)

JIT compiles Dart code to machine code as the program runs, just before each piece of code is executed. This makes the famous hot reload possible — you change your code, save the file, and the running app reflects the change in under a second without losing state.

JIT is used only during development.

AOT (Ahead-Of-Time)

AOT compiles all Dart code to native machine code before the app starts. The result is a self-contained binary that starts faster and runs more efficiently than JIT-compiled code.

AOT is used for all production builds — release APKs, iOS apps, and web builds.


Dart Garbage Collection

Dart uses automatic garbage collection to manage memory. You allocate objects and Dart frees them when they are no longer reachable — you never call free() or delete.

Dart uses a generational garbage collection strategy:

md
Generational GC
----------------
New Objects --> Young Generation (collected frequently)
                     |
                     | (objects that survive multiple collections)
                     v
               Old Generation (collected less frequently)

  • Young generation — short-lived objects (temporary variables, intermediate calculations). Collected frequently and cheaply.
  • Old generation — long-lived objects (app state, cached data). Collected less often.

This strategy minimizes GC pauses by focusing collection effort on the objects most likely to be garbage.


Concurrency in Dart

Dart handles concurrency through two mechanisms: Isolates and async programming.

Isolates

An Isolate is an independent unit of execution with its own memory heap. Isolates do not share memory — they communicate exclusively through message passing.

md
Isolate Architecture
---------------------
Main Isolate                Background Isolate
+-------------+             +-------------+
|  UI thread  |  <--msgs--> |  Worker     |
|  Event loop |             |  Heavy work |
+-------------+             +-------------+
   Own heap                    Own heap
   (no sharing)                (no sharing)

This design eliminates race conditions and data corruption from shared-memory concurrency.

dart
import 'dart:isolate';

void heavyComputation(SendPort sendPort) {
  // Runs in a separate isolate
  int result = 0;
  for (int i = 0; i < 1000000; i++) result += i;
  sendPort.send(result);
}

void main() async {
  final receivePort = ReceivePort();
  await Isolate.spawn(heavyComputation, receivePort.sendPort);
  final result = await receivePort.first;
  print('Result: $result');
}

Async Programming

For I/O-bound operations (network requests, file reads), Dart uses async/await on a single-threaded event loop — no need for separate threads or isolates.

dart
Future<void> loadData() async {
  print('Starting...');
  final data = await fetchFromServer(); // Does not block the event loop
  print('Data: $data');
}


Core Dart Libraries

LibraryPurpose
dart:coreAutomatically imported — basic types, collections, print
dart:asyncFuture, Stream, Completer for async programming
dart:ioFile I/O, HTTP server, network sockets
dart:convertJSON and UTF-8 encoding/decoding
dart:mathMathematical functions, constants, random numbers
dart:collectionExtended collection types (Queue, LinkedList, etc.)

A Minimal Dart Program

dart
void main() {
  // Print to console
  print('Hello, Dart!');

  // Variables
  String name = 'Amr';
  int age = 30;
  double height = 1.82;
  bool isFlutterDev = true;

  // String interpolation
  print('$name is $age years old and ${height}m tall.');
  print('Flutter developer: $isFlutterDev');
}


Why Dart?

FeatureBenefit
Static typingCatches errors at compile time, better IDE support
AOT compilationFast startup, smooth runtime, ideal for mobile
JIT + hot reloadRapid iteration during development
Async-first designClean, readable asynchronous code
Single-threaded + IsolatesSafe concurrency without shared-memory bugs
Null safetyEliminates null reference errors by design

Dart is a language designed for the use cases Flutter developers face every day. Learning it deeply — not just enough to write widgets — unlocks the full power of the Flutter platform.