SharedPreferences
Introduzione
Come possiamo salvare localmente alcune informazioni?
Esempi comuni:
- un flag
isLoggedIn
- il nome dell’utente
- un filtro selezionato (es. “solo completati”)
- il tema selezionato (dark/light mode)
- una mappa o una lista di valori semplici
Flutter offre il pacchetto SharedPreferences
, un sistema chiave/valore simile a localStorage
del web, ma asincrono e tipizzato.
Caratteristiche principali
Caratteristica | Descrizione |
---|---|
Persistente | I dati rimangono salvati tra sessioni |
Tipi semplici | String, int, double, bool, List<String> |
Supporto JSON manuale | Oggetti complessi vanno convertiti |
Asincrono | Tutti i metodi sono async/await |
Setup
Nel pubspec.yaml
:
dependencies:
shared_preferences: ^2.2.0
Import:
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:convert';
Metodi disponibili
Setters
prefs.setBool('key', true);
prefs.setInt('key', 1);
prefs.setDouble('key', 3.14);
prefs.setString('key', 'ciao');
prefs.setStringList('key', ['a', 'b']);
Getters
prefs.getBool('key');
prefs.getInt('key');
prefs.getDouble('key');
prefs.getString('key');
prefs.getStringList('key');
Altri
prefs.remove('key'); // rimuove un valore
prefs.clear(); // rimuove tutto
prefs.containsKey('key'); // verifica se esiste
Esempio: salva un flag
final prefs = await SharedPreferences.getInstance();
await prefs.setBool('isLoggedIn', true);
final logged = prefs.getBool('isLoggedIn') ?? false;
Esempio pratico: salva filtro (UI)
class FilterPage extends StatefulWidget {
const FilterPage({super.key});
@override
State<FilterPage> createState() => _FilterPageState();
}
class _FilterPageState extends State<FilterPage> {
bool completedOnly = false;
@override
void initState() {
super.initState();
loadFilter();
}
Future<void> loadFilter() async {
final prefs = await SharedPreferences.getInstance();
setState(() {
completedOnly = prefs.getBool('completedOnly') ?? false;
});
}
Future<void> updateFilter(bool value) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setBool('completedOnly', value);
setState(() {
completedOnly = value;
});
}
@override
Widget build(BuildContext context) {
return SwitchListTile(
title: const Text('Solo completati'),
value: completedOnly,
onChanged: updateFilter,
);
}
}
Salvare una mappa
SharedPreferences non supporta direttamente oggetti complessi come Map
, ma possiamo usare jsonEncode
,jsonDecode
.
Future<void> saveMap() async {
final prefs = await SharedPreferences.getInstance();
Map<String, dynamic> user = {
'id': 1,
'name': 'Mario Rossi',
'loggedIn': true,
};
final encoded = jsonEncode(user);
await prefs.setString('user_data', encoded);
}
Future<Map<String, dynamic>?> loadMap() async {
final prefs = await SharedPreferences.getInstance();
final jsonString = prefs.getString('user_data');
if (jsonString != null) {
return jsonDecode(jsonString);
}
return null;
}
Cancellare i dati
final prefs = await SharedPreferences.getInstance();
await prefs.remove('user_data'); // rimuove un singolo valore
await prefs.clear(); // rimuove tutto
Differenze con localStorage Web
Flutter (SharedPreferences ) | Web (localStorage ) |
---|---|
Tipizzato | Solo stringhe |
Asincrono | Sincrono |
Sicuro (sandboxed) | Accessibile da tutto JS |
Flutter Secure Storage
Per salvare dati sensibili (es. token di autenticazione, password, chiavi API), è consigliato usare il pacchetto flutter_secure_storage
, che memorizza i dati in modo cifrato su iOS (Keychain) e Android (Keystore).
Setup
Nel pubspec.yaml
:
dependencies:
flutter_secure_storage: ^9.0.0
Import:
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
Utilizzo base
final storage = FlutterSecureStorage();
// Scrittura
await storage.write(key: 'auth_token', value: 'ABC123');
// Lettura
String? token = await storage.read(key: 'auth_token');
// Rimozione
await storage.delete(key: 'auth_token');
// Cancellazione totale
await storage.deleteAll();
Quando usarlo
- Token JWT o sessione utente
- Dati bancari o credenziali
- Impostazioni private o sensibili
Quando usarlo
- Login persistente
- Preferenze utente (es. tema)
- Filtri selezionati
- Configurazioni salvate localmente
Esercitazione: Stato, Navigazione e SharedPreferences
Obiettivo
Sviluppa una piccola app Flutter che simula un sistema di login e memorizza lo stato utente utilizzando SharedPreferences
. L’app deve essere in grado di:
- Gestire il login/logout simulato
- Navigare tra schermate in base allo stato dell’utente
- Memorizzare localmente se l’utente è loggato o meno
- Usare
Provider
oBLoC
per gestire lo stato globale
Requisiti
1. Schermata di Login
- Mostra due
TextField
per email e password - Un pulsante “Login” che:
- Verifica se email e password sono valorizzati
- Salva
isLoggedIn = true
su SharedPreferences - Aggiorna lo stato globale con Provider/BLoC
- Naviga alla Home
2. Schermata Home
- Visualizza “Benvenuto” e un bottone Logout
- Il pulsante Logout:
- Cancella
isLoggedIn
da SharedPreferences - Aggiorna lo stato globale
- Naviga alla schermata di Login
3. Stato iniziale
- Al lancio dell’app, verifica da
SharedPreferences
seisLoggedIn == true
- Mostra direttamente la
HomePage
se l’utente è autenticato
Tecnologie richieste
SharedPreferences
per persistere lo stato utenteProvider
oppureflutter_bloc
Navigator
oppurego_router
Struttura consigliata
/lib
/models
user_model.dart (opzionale)
/screens
login_screen.dart
home_screen.dart
/state
auth_provider.dart (o auth_bloc.dart + auth_event/state)
/services
local_storage_service.dart
main.dart
Funzionalità bonus (facoltative)
All’interno di una pagina settings
- Memorizzare anche la preferenza di tema (dark/light)
- Aggiungere un pulsante per cancellare tutti i dati salvati