Dart — język programowania od Google, stworzony specjalnie dla wieloplatformowego frameworka Flutter. Łączy kompilację JIT dla błyskawicznego gorącego przeładowania i kompilację AOT dla natywnej wydajności w wersjach release. Dart jest używany nie tylko w programowaniu mobilnym, ale także w aplikacjach webowych (AngularDart) i rozwiązaniach serwerowych. Więcej o możliwościach języka przeczytasz w oficjalnej dokumentacji Dart.
Najważniejsze
Dart — język programowania ze składnią w stylu C, opracowany przez Google pod kierunkiem Larsa Bakka (twórcy Eclipse). Pierwsze wydanie miało miejsce w 2011 roku, ale prawdziwą popularność Dart zyskał w 2018 roku wraz z premierą Flutter 1.0. Język został zaprojektowany do tworzenia interfejsów użytkownika: ma wbudowane wsparcie dla strumieni, future i wzorców reaktywnych.
Filozofia Dart — „równowaga wydajności i produktywności". Język wspiera dwie strategie kompilacji: JIT (Just-In-Time) do programowania z gorącym przeładowaniem i AOT (Ahead-Of-Time) dla wersji release z natywną wydajnością. Kompilator JIT wstrzykuje zmodyfikowany kod do działającej aplikacji w milisekundach, nie wymagając ponownej kompilacji APK — to kluczowa zaleta Dart w porównaniu z innymi językami w kontekście programowania mobilnego.
Kluczowa cecha Dart — sound null safety, wprowadzona w Dart 2.12 (2021). System typów gwarantuje, że zmienna nie może być null bez jawnego wskazania (int?). Eliminuje to NullPointerException na etapie kompilacji. Według danych Google, wdrożenie null safety zmniejszyło liczbę crashy w aplikacjach Flutter o 30% w środowisku produkcyjnym.
Ekosystem Dart obejmuje trzy główne kierunki: Flutter (aplikacje mobilne i desktopowe), AngularDart (aplikacje webowe) i Dart Server (rozwiązania serwerowe). Flutter — dominująca platforma: według danych Statista (2025), Flutter jest używany w 46% wieloplatformowych projektów mobilnych, wyprzedzając React Native (38%) i Xamarin (8%).
Składnia Dart przypomina Java i JavaScript, ale ma własne unikalne konstrukcje. Wszystko w Dart jest obiektem — nawet int, double i bool dziedziczą po Object. Typowanie jest opcjonalne: zmienna zadeklarowana jako var inferuje typ automatycznie, ale zaleca się jawne określanie typów dla czytelności i wydajności.
Dart obsługuje int, double, String, bool, List, Set, Map, Record, Symbol i Runes. Typ nullable — dowolny typ z sufiksem ? (int?, String?). Operator ?? (null-aware) zwraca wartość po prawej, jeśli po lewej jest null. Notacja kaskadowa (..) pozwala wywołać wiele metod na jednym obiekcie bez powtarzania referencji.
// Podstawowe typy i deklaracje w Dart
void main() {
// Jawne typowanie
int age = 25;
double price = 19.99;
String name = 'Dart';
bool isValid = true;
// Null safety — zmienna może być null
int? nullableAge = null;
int result = nullableAge ?? 0; // Operator null-aware
// Kolekcje z generykami
List<String> items = ['Dart', 'Flutter', 'Mobile'];
Map<String, dynamic> config = {
'version': '3.0',
'mode': 'debug',
};
// Notacja kaskadowa
final list = <String>[]
..add('one')
..add('two')
..sort();
}
// Record — anonimowy niezmienny typ
(String, int) user = ('Alice', 30);
print(user.$1); // 'Alice'Typ dynamic wyłącza sprawdzanie typów — używaj go tylko przy pracy z JSON lub danymi dynamicznymi. Record — nowy typ w Dart 3.0, pozwalający grupować wartości bez tworzenia osobnej klasy. Operator null-aware ?? — standardowy sposób pracy z wartościami nullable, zastępujący długie sprawdzenia if-else.
Klasy w Dart — pojedyncze dziedziczenie (extends), wielokrotne przez mixiny (mixin). Dart nie obsługuje interfejsów jako osobnej koncepcji — każda klasa może być implementowana (implements). Mixin — klasa bez konstruktora, której metody i pola mogą być dodane do dowolnej klasy przez słowo kluczowe with.
// Klasy, dziedziczenie i mixiny w Dart
abstract class Animal {
void sound(); // abstrakcyjna metoda
}
mixin Swimmer {
void swim() => print('Swimming...');
}
mixin Flyer {
void fly() => print('Flying...');
}
class Duck extends Animal with Swimmer, Flyer {
@override
void sound() => print('Quack!');
}
void main() {
final duck = Duck();
duck.sound(); // Quack!
duck.swim(); // Swimming...
duck.fly(); // Flying...
}
// Nazwany konstruktor
class Config {
final String env;
Config.development() : env = 'dev';
Config.production() : env = 'prod';
}Klasa Duck dziedziczy po Animal i używa dwóch mixinów — Swimmer i Flyer. To demonstruje wielokrotne dziedziczenie bez problemów struktury rombowej: mixiny są rozwiązywane liniowo (super chain). Konstruktory nazwane (Config.development) — alternatywa dla statycznych metod fabrycznych do tworzenia obiektów z predefiniowanymi parametrami.
Asynchroniczność w Dart jest zrealizowana przez Future (pojedyncza wartość), Stream (sekwencja wartości) i async/await. Dart używa jednowątkowej pętli zdarzeń (event loop), podobnie jak JavaScript, ale z istotną różnicą: długotrwałe obliczenia nie blokują UI, ponieważ kod Dart wykonuje się w Isolate — oddzielnym wątku bez współdzielonej pamięci.
Future reprezentuje operację asynchroniczną, która zakończy się po pewnym czasie. Future może być w stanie pending (oczekiwanie), completed with value (sukces) lub completed with error (błąd). Łańcuch .then().catchError() — alternatywa dla async/await, ale zaleca się używanie await dla czytelności.
// Asynchroniczne ładowanie danych z Future i Stream
import 'dart:convert';
import 'package:http/http.dart' as http;
class ApiService {
final String baseUrl;
ApiService(this.baseUrl);
// Future dla pojedynczego zapytania
Future<Map<String, dynamic>> fetchUser(int id) async {
final response = await http.get(
Uri.parse('$baseUrl/users/$id'),
);
if (response.statusCode == 200) {
return jsonDecode(response.body);
} else {
throw Exception('Failed to load user: ${response.statusCode}');
}
}
// Stream dla sekwencji danych
Stream<int> countStream(int max) async* {
for (var i = 1; i <= max; i++) {
await Future.delayed(Duration(seconds: 1));
yield i;
}
}
}
void main() async {
final api = ApiService('https://api.example.com');
// Użycie await
final user = await api.fetchUser(1);
print('User: ${user['name']}');
// Obsługa Stream z await for
await for (final count in api.countStream(5)) {
print('Count: $count');
}
}Klasa ApiService demonstruje dwa typy asynchroniczności: Future dla zapytania HTTP (jedna odpowiedź) i Stream dla sekwencyjnego licznika (generator z async* i yield). Stream jest wydajny do pracy z czujnikami, geolokalizacją, Firebase Realtime Database — wszędzie tam, gdzie dane napływają w sposób ciągły. Isolate używa oddzielnej pamięci — dane są przesyłane przez SendPort/ReceivePort.
Dart i Flutter tworzą jeden stos: Flutter — framework UI, Dart — język opisu UI. W Flutter wszystko jest widżetem (Widget) — od przycisku do całej aplikacji. Widżety mogą być stateful (ze zmiennym stanem) i stateless (niezmienne). Dart opisuje deklaratywny UI: build() zwraca drzewo widżetów, które Flutter renderuje za pomocą Skia (lub Impeller na iOS).
Aplikacja Flutter w Dart składa się z main() → runApp(MyApp()) → MaterialApp. MaterialApp zawiera routing (routes), motyw (theme) i lokalizację. Każdy ekran to Scaffold, zawierający AppBar, Body (zwykle Column/ListView) i BottomNavigationBar. Nawigacja przez Navigator.push/pop lub nazwane trasy.
// Prosta aplikacja Flutter w Dart
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Dart Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: HomeScreen(),
);
}
}
class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
int _counter = 0;
void _increment() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Dart + Flutter')),
body: Center(
child: Text('Counter: $_counter'),
),
floatingActionButton: FloatingActionButton(
onPressed: _increment,
child: Icon(Icons.add),
),
);
}
}Widżet HomeScreen — StatefulWidget z wewnętrznym stanem _counter. Wywołanie setState() informuje Flutter o konieczności przebudowy UI — kod Dart restartuje build(), tworząc nowe drzewo widżetów. Flutter efektywnie porównuje (diff) stare i nowe drzewo, aktualizując tylko zmienione części ekranu. Hot Reload zastępuje build() bez resetowania stanu _counter.
Kompilacja Dart — hybrydowa: JIT do programowania i AOT do produkcji. W trybie debugowania Dart VM uruchamia kompilator JIT, który interpretuje kod bajtowy z możliwością gorącej wymiany kodu. W wersji release dart compile exe lub flutter build tworzy natywny binarny plik AOT dla konkretnej architektury (arm64, x86_64, armv7).
| Tryb | Kompilacja | Szybkość wykonania | Rozmiar binaru | Hot Reload |
|---|---|---|---|---|
| Debug | JIT (VM) | Średnia | ~50 MB | Tak |
| Release | AOT (Native) | Maksymalna | ~15-20 MB | Nie |
| Web | dart2js | Zależy od przeglądarki | Zmienny | Dev-server |
Kompilacja JIT Dart w trybie debugowania zapewnia gorące przeładowanie w ciągu ~1 sekundy — programista widzi zmiany UI bez utraty stanu aplikacji. Kompilacja AOT daje wydajność zbliżoną do natywnych aplikacji Swift/Kotlin. Według danych Google, Flutter na Dart AOT osiąga 60 FPS animacji nawet na urządzeniach średniej klasy.
Narzędzia programisty Dart obejmują Dart SDK (kompilator dart, dartanalyzer, dartfmt, pub), Flutter SDK i wtyczki IDE. Dart SDK jest instalowany razem z Flutter SDK w folderze flutter/bin/cache/dart-sdk. Pub — menedżer pakietów, czytający pubspec.yaml i pobierający zależności z pub.dev.
dart analyze — statyczny analizator, sprawdzający typy, nieużywane importy i potencjalne błędy. dart format — formatator, automatycznie dostosowujący kod do jednolitego stylu. dart doc — generator dokumentacji z komentarzy ///. Flutter DevTools — profiler z podglądem drzewa widżetów, logów, pamięci i sieci. Dart VM Service — debugowanie działającej aplikacji przez WebSocket.
# pubspec.yaml — konfiguracja projektu Dart
name: my_flutter_app
description: A new Flutter project.
version: 1.0.0
environment:
sdk: '>=3.0.0 <4.0.0'
dependencies:
flutter:
sdk: flutter
http: ^1.2.0
provider: ^6.1.0
shared_preferences: ^2.2.0
json_annotation: ^4.8.0
dev_dependencies:
flutter_test:
sdk: flutter
build_runner: ^2.4.0
json_serializable: ^6.7.0
flutter_lints: ^3.0.0Plik pubspec.yaml opisuje zależności projektu Dart. Pole environment:sdk określa wersję Dart — obecna stabilna 3.x. Dependencies — główne biblioteki, dev_dependencies — do testowania i generowania kodu. json_annotation + json_serializable generują kod do serializacji JSON przez build_runner. flutter_lints — zestaw reguł dla analizatora.
Często zadawane pytania
Dart — język programowania od Google (2011), zaprojektowany do wieloplatformowego rozwoju na Flutter. Obsługuje składnię w stylu C, silne typowanie, kompilację JIT i AOT. Wyróżnia się sound null safety (od Dart 2.12) i asynchronicznością przez Future i Stream. Używany do aplikacji mobilnych, webowych i desktopowych.
Dart kompiluje się do natywnego kodu (AOT) lub JS (dart2js), JavaScript — jest interpretowany. Dart ma silne typowanie z sound null safety, wbudowane klasy i mixiny. Asynchroniczność Dart opiera się na Isolate (oddzielne wątki bez współdzielonej pamięci), JS — na pętli zdarzeń z Web Workers. Wydajność Dart AOT jest o 30-50% wyższa niż V8 JIT w scenariuszach mobilnych.
Dart kompiluje się AOT do natywnego kodu ARM przez Dart Native. W trybie debugowania Dart VM używa JIT z gorącym przeładowaniem. Flutter Engine (C++) renderuje UI przez Skia/Impeller. Dla Androida — flutter build apk, dla iOS — flutter build ios. Kompilacja web używa dart2js lub dart2wasm. Rozmiar APK wersji release — 15-20 MB (bez podziału AAB).
Dart obsługuje typy prymitywne: int, double, String, bool. Kolekcje: List, Set, Map, Record. Specjalne: Symbol, Runes, Null. Wszystko jest obiektem, łącznie z prymitywami. Null safety: typ int? dopuszcza null, int — nigdy null. Operatory ??, ??= do bezpiecznej pracy z null. Generyki: List<String>, Map<String, dynamic>.
Flutter SDK zawiera Dart SDK, Flutter Engine i bibliotekę widżetów. IDE — Android Studio lub VS Code z wtyczką Flutter. DevTools — profiler z inspektorem widżetów. Pub.dev — menedżer pakietów z 45 000+ bibliotek. Analizator dart analyze i formatator dart format — dla jakości kodu. Build_runner — do generowania modeli JSON.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również