Persistenza dei dati locali in Flutter con shared_preferences
GuidePrincipiante25 min Flutter 3.x

Persistenza dei dati locali in Flutter con shared_preferences

In molte app è necessario memorizzare piccole quantità di dati in modo persistente: il tema scelto dall'utente, un flag che indica se l'onboarding è già stato completato, o l'ultimo username inserito.

Il pacchetto shared_preferences è la soluzione ideale per questi casi: salva coppie chiave-valore in modo persistente sfruttando i meccanismi nativi di ogni piattaforma (NSUserDefaults su iOS, SharedPreferences su Android, ecc.).

In questo tutorial costruiremo una piccola app che salva e ripristina le preferenze dell'utente, e vedremo come incapsulare la logica in un servizio riutilizzabile.

  1. 1

    Aggiungere la dipendenza

    Per prima cosa aggiungiamo il pacchetto shared_preferences al nostro progetto. Puoi usare il comando da terminale oppure modificare direttamente il file pubspec.yaml.

    Usa il comando seguente nella cartella del progetto:

    flutter pub add shared_preferences

    Risultato atteso

    Nel file pubspec.yaml comparirà la dipendenza shared_preferences sotto la sezione dependencies e le dipendenze verranno scaricate.

  2. 2

    Creare un servizio per le preferenze

    Per mantenere il codice ordinato, incapsuliamo la logica di lettura e scrittura in una classe dedicata. In questo modo evitiamo di sparpagliare le chiamate a SharedPreferences in tutta l'app.

    Creiamo il file lib/services/preferences_service.dart con metodi per salvare e leggere il nome utente e una flag booleana per il tema scuro.

    import 'package:shared_preferences/shared_preferences.dart';
    
    class PreferencesService {
      static const _keyUsername = 'username';
      static const _keyDarkMode = 'dark_mode';
    
      Future<void> saveUsername(String username) async {
        final prefs = await SharedPreferences.getInstance();
        await prefs.setString(_keyUsername, username);
      }
    
      Future<String?> getUsername() async {
        final prefs = await SharedPreferences.getInstance();
        return prefs.getString(_keyUsername);
      }
    
      Future<void> setDarkMode(bool value) async {
        final prefs = await SharedPreferences.getInstance();
        await prefs.setBool(_keyDarkMode, value);
      }
    
      Future<bool> isDarkMode() async {
        final prefs = await SharedPreferences.getInstance();
        return prefs.getBool(_keyDarkMode) ?? false;
      }
    }

    Risultato atteso

    Avrai una classe PreferencesService riutilizzabile con metodi asincroni per gestire username e tema.

  3. 3

    Costruire l'interfaccia utente

    Creiamo una semplice schermata con un TextField per inserire lo username e uno Switch per attivare il tema scuro. Usiamo uno StatefulWidget per gestire lo stato locale dei controlli.

    import 'package:flutter/material.dart';
    import 'services/preferences_service.dart';
    
    class SettingsPage extends StatefulWidget {
      const SettingsPage({super.key});
    
      @override
      State<SettingsPage> createState() => _SettingsPageState();
    }
    
    class _SettingsPageState extends State<SettingsPage> {
      final _service = PreferencesService();
      final _controller = TextEditingController();
      bool _darkMode = false;
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: const Text('Impostazioni')),
          body: Padding(
            padding: const EdgeInsets.all(16),
            child: Column(
              children: [
                TextField(
                  controller: _controller,
                  decoration: const InputDecoration(labelText: 'Username'),
                ),
                SwitchListTile(
                  title: const Text('Tema scuro'),
                  value: _darkMode,
                  onChanged: (v) => setState(() => _darkMode = v),
                ),
                const SizedBox(height: 16),
                ElevatedButton(
                  onPressed: _save,
                  child: const Text('Salva'),
                ),
              ],
            ),
          ),
        );
      }
    
      Future<void> _save() async {}
    }

    Risultato atteso

    Una schermata Impostazioni con campo testo, switch e pulsante Salva, ancora non collegati alla persistenza.

  4. 4

    Salvare i dati al tocco del pulsante

    Implementiamo il metodo _save per scrivere i valori inseriti dall'utente tramite il nostro PreferencesService. Mostriamo anche uno SnackBar di conferma.

    Future<void> _save() async {
      await _service.saveUsername(_controller.text);
      await _service.setDarkMode(_darkMode);
    
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('Preferenze salvate!')),
      );
    }

    Risultato atteso

    Premendo Salva i dati vengono persistiti sul dispositivo e appare un messaggio di conferma.

  5. 5

    Caricare i dati all'avvio

    Per ripristinare le preferenze salvate quando l'utente riapre la schermata, leggiamo i valori in initState. Poiché le chiamate sono asincrone, usiamo un metodo separato e aggiorniamo lo stato con setState.

    @override
    void initState() {
      super.initState();
      _loadPreferences();
    }
    
    Future<void> _loadPreferences() async {
      final username = await _service.getUsername();
      final darkMode = await _service.isDarkMode();
    
      if (!mounted) return;
      setState(() {
        _controller.text = username ?? '';
        _darkMode = darkMode;
      });
    }

    Risultato atteso

    Riaprendo l'app o la schermata, i valori precedentemente salvati appaiono già compilati nei controlli.

  6. 6

    Aggiungere un metodo per cancellare i dati

    Infine è utile poter ripristinare le impostazioni di default. Aggiungiamo al servizio un metodo per rimuovere una singola chiave o azzerare tutte le preferenze, e colleghiamolo a un pulsante.

    Nota: usa remove per cancellare una chiave specifica e clear per eliminare tutto. Attenzione: clear rimuove anche i dati salvati da altre parti dell'app.

    // In PreferencesService
    Future<void> clearAll() async {
      final prefs = await SharedPreferences.getInstance();
      await prefs.clear();
    }
    
    // Nella UI, ad esempio in un pulsante:
    ElevatedButton(
      onPressed: () async {
        await _service.clearAll();
        if (!mounted) return;
        setState(() {
          _controller.clear();
          _darkMode = false;
        });
      },
      child: const Text('Ripristina default'),
    )

    Risultato atteso

    Premendo il pulsante di ripristino, tutte le preferenze vengono cancellate e i controlli tornano ai valori di default.

CondividiXLinkedInFacebookWhatsApp

Commenti (0)

Ancora nessun commento. Inizia tu!