3.5 - Approfondimenti su Dart
Collezioni
Dart offre diversi tipi di collezioni come List, Map e Set, insieme agli operatori spread e collection if, molto utili nella costruzione delle interfacce in Flutter.
Liste
void main() {
List<int> numeri = [1, 2, 3];
// Aggiungi un elemento
numeri.add(4);
print(numeri); // Output: [1, 2, 3, 4]
}
Operatori Avanzati per Collezioni
I collection operators consentono di creare e manipolare liste in modo conciso e leggibile.
void main() {
// Spread operator: espande una lista all'interno di un'altra
List<int> lista1 = [1, 2];
List<int> lista2 = [0, ...lista1, 3];
print("Lista espansa: $lista2"); // Output: [0, 1, 2, 3]
// Collection if: aggiunge elementi condizionalmente
bool aggiungi = true;
List<String> elementi = [
"Base",
if (aggiungi) "Aggiuntivo"
];
print("Lista condizionale: $elementi");
// Collection for: crea una nuova lista iterando su una collezione esistente
List<int> quadrati = [for (var x in lista1) x * x];
print("Quadrati: $quadrati"); // Output: [1, 4]
}
Mappe
void main() {
Map<String, int> mappa = {
'uno': 1,
'due': 2
};
mappa['tre'] = 3;
print(mappa); // Output: {uno: 1, due: 2, tre: 3}
}
Set
void main() {
Set<String> insiemi = {'a', 'b', 'c'};
insiemi.add('d');
print(insiemi); // Output: {a, b, c, d}
}
3. Funzioni Arrow e Funzioni Anonime
Le funzioni arrow permettono di scrivere funzioni in modo compatto.
Funzione Arrow
int somma(int a, int b) => a + b;
void main() {
print(somma(3, 4)); // Output: 7
}
Funzioni Anonime
void main() {
var lista = [1, 2, 3, 4];
lista.forEach((numero) {
print("Numero: $numero");
});
}
Uso degli Stream
void main() {
// Crea uno Stream che emette un numero intero ogni secondo, per 3 eventi
Stream<int> contatore = Stream.periodic(Duration(seconds: 1), (x) => x).take(3);
// Ascolta lo Stream e stampa ciascun valore emesso
contatore.listen((valore) {
print("Evento stream: $valore");
});
}
4. Programmazione Asincrona: Future, async/await e Stream
La programmazione asincrona è fondamentale in Flutter per gestire operazioni come chiamate di rete e accesso a database.
Uso di Future con async/await
// Una funzione asincrona che simula una richiesta (es. API) con un ritardo
Future<String> fetchData() async {
await Future.delayed(Duration(seconds: 2));
return "Dati ricevuti";
}
void main() async {
print("Inizio richiesta...");
String dati = await fetchData(); // Attende il completamento della richiesta
print(dati); // Output: Dati ricevuti (dopo 2 secondi)
}
Stream
Gli Stream permettono di gestire sequenze di eventi asincroni.
void main() {
// Creazione di uno Stream che emette valori interi
Stream<int> stream = Stream.periodic(Duration(seconds: 1), (count) => count).take(5);
stream.listen((d) {
print("Evento: $d");
});
}
5. Generici
I generici permettono di creare classi e funzioni che lavorano con diversi tipi in modo sicuro.
Esempio di Classe Generica
class Coppia<T, U> {
T primo;
U secondo;
Coppia(this.primo, this.secondo);
}
void main() {
var coppia = Coppia<int, String>(1, "uno");
print("Primo: ${coppia.primo}, Secondo: ${coppia.secondo}");
}