Tag: flutter, dart, mobile, cross-platform, widgets, state-management
Livello: intermedio
TL;DR: Framework UI dichiarativo cross-platform basato su Dart. Tutto è un Widget, rendering gestito via canvas Skia/Impeller e separazione tra Widget, Element e RenderObject.
Tutto è un Widget: classi immutabili che descrivono la configurazione della UI.
Albero triplo: Widget (configurazione), Element (istanza e ciclo di vita), RenderObject (layout e pittura).
StatelessWidget: widget immutabile senza stato interno, ricostruito solo al variare dei parametri in ingresso.
StatefulWidget: mantiene lo stato persistente tramite una classe State separata tra vari rebuild.
Motore di rendering grafico dedicato (Impeller o Skia), evitando i widget nativi della piattaforma.
Linguaggio Dart: compilazione AOT per produzione ad alte prestazioni e JIT per Hot Reload rapido in sviluppo.
Hot Reload: inietta il codice sorgente aggiornato nella Dart VM mantenendo lo stato applicativo intatto.
Hot Restart: ricompila il codice e azzera completamente lo stato dell'app riavviando l'entrypoint.
Gestione dello stato: approcci integrati (InheritedWidget) o architetturali (Bloc/Cubit, Riverpod, Provider).
Platform Channels: comunicazione asincrona binaria basata su messaggi per invocare API native iOS/Android.
Q: Qual è la differenza tra StatelessWidget e StatefulWidget?R: StatelessWidget descrive un'interfaccia immutabile basata esclusivamente sui parametri ricevuti. StatefulWidget associa un'istanza di State separata che sopravvive ai cicli di build e può mutare nel tempo tramite setState.
Q: Come funziona il meccanismo di rendering e perché Flutter non usa le view native?R: Flutter controlla ogni singolo pixel disegnando direttamente su canvas tramite il proprio engine C++ (Impeller/Skia). Questo elimina il bridge a runtime verso le view native garantendo 60/120 fps costanti e parità grafica totale.
Q: Quando si usa FutureBuilder rispetto a StreamBuilder?R: FutureBuilder gestisce operazioni asincrone a valore singolo che si risolvono una sola volta (come chiamate HTTP). StreamBuilder si mette in ascolto di flussi continui di dati nel tempo (come WebSocket o eventi di sensori).
Q: Cosa succede sotto il cofano quando chiami setState?R: setState marca l'Element associato come dirty e pianifica una nuova esecuzione del metodo build per il frame successivo nel widget tree locale.
Invocare computazioni pesanti o chiamate asincrone direttamente dentro il metodo build.
Mancato dispose di Controller, StreamSubscription o FocusNode nei metodi dispose() di uno State.
Chiamare setState su un widget State dopo che è stato rimosso dall'albero (eccezione setState called after dispose).
Usare costruttori non const per widget statici, causando rebuild inutili dell'intero sotto-albero.
Errori di layout unbounded constraints (ad esempio inserire una ListView non shrink-wrapped dentro una Column).
Eseguire operazioni CPU-intensive sul main isolate di Dart bloccando il frame rate (usare compute o worker isolate).
# Verifica configurazione ambiente e dipendenze
flutter doctor -v
# Esecuzione in debug o release su dispositivo target
flutter run -d chrome
flutter run --release
# Analisi statica del codice e formattazione
flutter analyze
dart format .
# Generazione di codice automatico (es. Freezed, JSON Serializable)
dart run build_runner build --delete-conflicting-outputs
Dart
// Esempio StatefulWidget con gestione corretta del ciclo di vita
class CounterView extends StatefulWidget {
const CounterView({super.key});
@override
State<CounterView> createState() => _CounterViewState();
}
class _CounterViewState extends State<CounterView> {
late final TextEditingController _controller;
int _counter = 0;
@override
void initState() {
super.initState();
_controller = TextEditingController();
}
void _increment() {
setState(() {
_counter++;
});
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(child: Text('Count: $_counter')),
floatingActionButton: FloatingActionButton(
onPressed: _increment,
child: const Icon(Icons.add),
),
);
}
}
[ ] Pattern Bloc / Cubit per separazione tra logica di business e interfaccia grafica
[ ] Riverpod e gestione della dependency injection compile-time
[ ] Architettura del motore di rendering: PipelineOwner, RenderBox e LayoutConstraints
[ ] Comunicazione nativa avanzata tramite FFI (Foreign Function Interface) e MethodChannel
[ ] Profilazione delle performance con Flutter DevTools (CPU profiler, raster thread, memory leaks)