5.1Stockage simple avec SharedPreferences
5.1.1 – Présentation de SharedPreferences
🎯 Qu'est-ce que SharedPreferences ?
SharedPreferences est un package Flutter qui permet de stocker des données simples sous forme de paires clé-valeur. Il s'agit d'une solution de stockage persistant, ce qui signifie que les données sont conservées même après la fermeture de l'application.
Ce mécanisme est particulièrement adapté pour :
- Les préférences utilisateur : thème (clair/sombre), langue, notifications activées/désactivées
- Les paramètres de l'application : volume par défaut, qualité d'affichage, mode de connexion
- Les petits compteurs ou états : nombre de fois que l'application a été ouverte, dernière version vue
- Les données de session simples : nom d'utilisateur, token d'authentification (pour des cas non sensibles)
SharedPreferences utilise le stockage natif de chaque plateforme :
- Sur Android : il utilise les SharedPreferences natifs d'Android (fichiers XML)
- Sur iOS : il utilise NSUserDefaults
- Sur Web : il utilise localStorage du navigateur
📊 Types de données supportés
SharedPreferences peut stocker les types de données suivants :
String: chaînes de caractèresint: nombres entiersdouble: nombres décimauxbool: valeurs booléennes (true/false)List<String>: listes de chaînes de caractères
SharedPreferences ne peut stocker que des types primitifs. Si vous avez besoin de stocker des objets complexes (comme une liste d'utilisateurs avec plusieurs propriétés), vous devrez soit :
- Convertir vos objets en JSON et les stocker comme des String
- Utiliser une solution plus adaptée comme SQLite ou Hive
âś… Avantages de SharedPreferences
- Simplicité : API très simple à utiliser, pas besoin de configuration complexe
- Rapidité : accès très rapide aux données
- Léger : pas de surcharge, idéal pour de petites quantités de données
- Persistance : les données survivent aux redémarrages de l'application
- Cross-platform : fonctionne de la même manière sur Android, iOS et Web
❌ Limites de SharedPreferences
- Types limités : seulement des types primitifs, pas d'objets complexes
- Pas de requĂŞtes : impossible de faire des recherches ou filtres complexes
- Pas de relations : pas de base de données relationnelle
- Performance : peut devenir lent avec beaucoup de données (plusieurs milliers d'entrées)
- Sécurité : les données ne sont pas chiffrées (utilisez Secure Storage pour les données sensibles)
Utilisez SharedPreferences si vous avez besoin de stocker :
- Moins de 100-200 paires clé-valeur
- Des données simples (String, int, bool, etc.)
- Des préférences utilisateur ou des paramètres
- Des données non sensibles
5.1.2 – Installation et configuration du package
🎯 Objectif
Installer le package SharedPreferences dans votre projet Flutter et le configurer correctement.
đź’ˇ Installation pas Ă pas
Étape 1 : Ajouter la dépendance
Ouvrez le fichier pubspec.yaml de votre projet Flutter et ajoutez la dépendance shared_preferences dans la section dependencies :
dependencies:
flutter:
sdk: flutter
shared_preferences: ^2.2.2
La version peut varier. Pour obtenir la dernière version, consultez pub.dev/packages/shared_preferences ou utilisez la commande :
flutter pub add shared_preferences
Cette commande ajoute automatiquement la dernière version compatible.
Étape 2 : Installer le package
Exécutez la commande suivante dans votre terminal, à la racine de votre projet Flutter :
flutter pub get
✅ Résultat attendu : Vous devriez voir un message indiquant que le package a été installé avec succès.
Étape 3 : Importer le package
Dans le fichier Dart oĂą vous souhaitez utiliser SharedPreferences, ajoutez l'import en haut du fichier :
import 'package:shared_preferences/shared_preferences.dart';
📖 Vérifier l'installation
import 'package:shared_preferences/shared_preferences.dart';
void main() {
print('SharedPreferences est prêt à être utilisé !');
}
Si aucune erreur n'apparaît, l'installation est réussie. ✅
Si vous utilisez VS Code ou Android Studio, l'IDE vous proposera automatiquement d'importer le package lorsque vous taperez
SharedPreferences dans votre code. C'est très pratique !
5.1.3 – Sauvegarder des données simples
Pour sauvegarder des données avec SharedPreferences, vous devez d'abord obtenir une instance, puis utiliser les méthodes set* correspondantes au type de données que vous voulez stocker.
📝 Qu'est-ce que la sauvegarde avec SharedPreferences ?
La sauvegarde consiste à stocker des données dans la mémoire persistante de l'appareil. Ces données seront conservées même après la fermeture de l'application.
SharedPreferences est comme un tiroir avec des étiquettes. Vous mettez une valeur dans un tiroir étiqueté avec une clé (par exemple "username"), et vous pouvez la récupérer plus tard en utilisant cette même clé.
📝 Syntaxe
Voici comment obtenir une instance de SharedPreferences et sauvegarder des données :
// Obtenir une instance (opération asynchrone)
SharedPreferences prefs = await SharedPreferences.getInstance();
// Sauvegarder une String
await prefs.setString('username', 'john_doe');
// Sauvegarder un int
await prefs.setInt('age', 25);
// Sauvegarder un double
await prefs.setDouble('price', 19.99);
// Sauvegarder un bool
await prefs.setBool('isDarkMode', true);
// Sauvegarder une liste de String
await prefs.setStringList('favoriteColors', ['red', 'blue', 'green']);
Analysons cette syntaxe :
SharedPreferences.getInstance(): Obtient une instance de SharedPreferences (opération asynchrone)setString(key, value): Sauvegarde une chaîne de caractèressetInt(key, value): Sauvegarde un nombre entiersetDouble(key, value): Sauvegarde un nombre décimalsetBool(key, value): Sauvegarde une valeur booléennesetStringList(key, value): Sauvegarde une liste de chaînes
L'initialisation de SharedPreferences nécessite l'accès au système de fichiers, ce qui est une opération asynchrone. C'est pourquoi vous devez utiliser
await et que votre fonction doit être async. 🔄
🧪 Exemple : Sauvegarder des préférences utilisateur
Voici un exemple complet qui sauvegarde les préférences d'un utilisateur :
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() {
runApp(const MonApp());
}
class MonApp extends StatelessWidget {
const MonApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: const MaPage(),
);
}
}
class MaPage extends StatefulWidget {
const MaPage({super.key});
@override
State<MaPage> createState() => _MaPageState();
}
class _MaPageState extends State<MaPage> {
final _nomController = TextEditingController();
final _ageController = TextEditingController();
Future<void> sauvegarderPreferences() async {
// Obtenir une instance
SharedPreferences prefs = await SharedPreferences.getInstance();
// Sauvegarder différentes données
await prefs.setString('nom', _nomController.text);
await prefs.setInt('age', int.tryParse(_ageController.text) ?? 0);
await prefs.setBool('themeSombre', true);
await prefs.setDouble('volume', 0.75);
// Afficher un message de confirmation
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Préférences sauvegardées !')),
);
}
}
@override
void dispose() {
_nomController.dispose();
_ageController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Sauvegarder avec SharedPreferences'),
),
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
TextField(
controller: _nomController,
decoration: const InputDecoration(
labelText: 'Nom',
border: OutlineInputBorder(),
),
),
const SizedBox(height: 16),
TextField(
controller: _ageController,
decoration: const InputDecoration(
labelText: 'Âge',
border: OutlineInputBorder(),
),
keyboardType: TextInputType.number,
),
const SizedBox(height: 24),
ElevatedButton(
onPressed: sauvegarderPreferences,
child: const Text('Sauvegarder'),
),
],
),
),
),
);
}
}
Dans cet exemple, quand l'utilisateur clique sur "Sauvegarder", les données sont stockées dans SharedPreferences et un message de confirmation s'affiche.
Toutes les méthodes
set* retournent un bool qui indique si la sauvegarde a réussi. Vous pouvez vérifier ce retour pour gérer les erreurs :
bool success = await prefs.setString('username', 'john_doe');
if (success) {
print('Données sauvegardées avec succès !');
} else {
print('Erreur lors de la sauvegarde');
}
N'oubliez pas que les opérations avec SharedPreferences sont asynchrones. Vous devez toujours utiliser
await et déclarer votre fonction comme async.💡 À propos de
mounted :Avant d'appeler
setState après une opération asynchrone, vérifiez toujours if (mounted). Cela permet d'éviter des erreurs si le widget a été retiré de l'arbre Flutter.
5.1.4 – Récupérer des données stockées
Pour récupérer des données sauvegardées avec SharedPreferences, vous utilisez les méthodes get* correspondantes au type de données que vous avez stocké.
📖 Qu'est-ce que la récupération de données ?
La récupération consiste à lire les données que vous avez précédemment sauvegardées. Ces données sont lues depuis la mémoire persistante de l'appareil.
C'est comme ouvrir un tiroir étiqueté pour récupérer ce que vous y avez mis. Si le tiroir est vide (la clé n'existe pas), vous obtenez
null.
📝 Syntaxe
Voici comment récupérer différents types de données :
// Obtenir une instance
SharedPreferences prefs = await SharedPreferences.getInstance();
// Récupérer une String (retourne null si la clé n'existe pas)
String? username = prefs.getString('username');
String username = prefs.getString('username') ?? 'Guest'; // Avec valeur par défaut
// Récupérer un int
int? age = prefs.getInt('age');
int age = prefs.getInt('age') ?? 0; // Avec valeur par défaut
// Récupérer un double
double? price = prefs.getDouble('price');
double price = prefs.getDouble('price') ?? 0.0; // Avec valeur par défaut
// Récupérer un bool
bool? isDarkMode = prefs.getBool('isDarkMode');
bool isDarkMode = prefs.getBool('isDarkMode') ?? false; // Avec valeur par défaut
// Récupérer une liste de String
List<String>? colors = prefs.getStringList('favoriteColors');
List<String> colors = prefs.getStringList('favoriteColors') ?? []; // Avec valeur par défaut
Analysons cette syntaxe :
getString(key): Récupère une chaîne de caractères (retournenullsi la clé n'existe pas)getInt(key): Récupère un nombre entiergetDouble(key): Récupère un nombre décimalgetBool(key): Récupère une valeur booléennegetStringList(key): Récupère une liste de chaînes??: Opérateur qui fournit une valeur par défaut si le résultat estnull
🧪 Exemple : Récupérer et afficher des préférences
Voici un exemple complet avec deux TextField (nom et âge) et un Switch (thème sombre). Les valeurs sont automatiquement chargées au démarrage et sauvegardées à chaque modification :
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() {
runApp(const MonApp());
}
class MonApp extends StatelessWidget {
const MonApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: const MaPage(),
);
}
}
class MaPage extends StatefulWidget {
const MaPage({super.key});
@override
State<MaPage> createState() => _MaPageState();
}
class _MaPageState extends State<MaPage> {
final _nomController = TextEditingController();
final _ageController = TextEditingController();
bool themeSombre = false;
@override
void initState() {
super.initState();
chargerPreferences();
}
// Charger les préférences au démarrage
Future<void> chargerPreferences() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
// Récupérer le nom (valeur par défaut : chaîne vide)
_nomController.text = prefs.getString('nom') ?? '';
// Récupérer l'âge (valeur par défaut : 0)
int age = prefs.getInt('age') ?? 0;
_ageController.text = age > 0 ? age.toString() : '';
// Récupérer l'état du thème (valeur par défaut : false)
themeSombre = prefs.getBool('themeSombre') ?? false;
});
}
// Sauvegarder le nom quand il change
Future<void> sauvegarderNom(String valeur) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setString('nom', valeur);
}
// Sauvegarder l'âge quand il change
Future<void> sauvegarderAge(String valeur) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
int age = int.tryParse(valeur) ?? 0;
await prefs.setInt('age', age);
}
// Sauvegarder l'état du thème quand il change
Future<void> sauvegarderTheme(bool valeur) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setBool('themeSombre', valeur);
}
@override
void dispose() {
_nomController.dispose();
_ageController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Préférences persistantes'),
),
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// TextField pour le nom
TextField(
controller: _nomController,
decoration: const InputDecoration(
labelText: 'Nom',
border: OutlineInputBorder(),
hintText: 'Entrez votre nom',
),
onChanged: (valeur) {
// Sauvegarder automatiquement Ă chaque modification
sauvegarderNom(valeur);
},
),
const SizedBox(height: 16),
// TextField pour l'âge
TextField(
controller: _ageController,
decoration: const InputDecoration(
labelText: 'Âge',
border: OutlineInputBorder(),
hintText: 'Entrez votre âge',
),
keyboardType: TextInputType.number,
onChanged: (valeur) {
// Sauvegarder automatiquement Ă chaque modification
sauvegarderAge(valeur);
},
),
const SizedBox(height: 24),
// Switch pour le thème sombre
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
'Thème sombre',
style: TextStyle(fontSize: 18),
),
Switch(
value: themeSombre,
onChanged: (bool valeur) {
setState(() {
themeSombre = valeur;
});
// Sauvegarder automatiquement quand le switch change
sauvegarderTheme(valeur);
},
),
],
),
const SizedBox(height: 24),
// Message informatif
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.blue.shade50,
borderRadius: BorderRadius.circular(8),
),
child: const Text(
'💡 Les valeurs sont automatiquement sauvegardées et seront restaurées au prochain démarrage de l\'application.',
style: TextStyle(fontSize: 14),
),
),
],
),
),
),
);
}
}
Dans cet exemple :
- Au démarrage : Les valeurs sauvegardées (nom, âge, thème) sont chargées depuis SharedPreferences et affichées dans les TextField et le Switch
- À chaque modification : Quand l'utilisateur modifie un TextField ou le Switch, la valeur est automatiquement sauvegardée dans SharedPreferences
- Persistance : Si vous fermez et rouvrez l'application, toutes les valeurs seront restaurées automatiquement
initState(): AppellechargerPreferences()au démarrage pour charger les valeurs sauvegardéesonChanged: Sur chaque TextField, sauvegarde automatiquement la valeur à chaque modificationonChangeddu Switch : Met à jour l'état et sauvegarde immédiatementTextEditingController: Permet de contrôler et initialiser le contenu des TextField
Vous pouvez vérifier si une clé existe avant de la récupérer :
bool exists = prefs.containsKey('username');
if (exists) {
String username = prefs.getString('username')!;
print('Username trouvé: $username');
} else {
print('La clé username n\'existe pas');
}
Vous pouvez obtenir toutes les clés stockées :
Set<String> keys = prefs.getKeys();
print('Clés stockées: $keys');
Comme les méthodes
get* peuvent retourner null, utilisez toujours l'opérateur ?? pour fournir une valeur par défaut. Cela évite les erreurs si la clé n'existe pas encore.
5.1.5 – Supprimer et modifier des données
Vous pouvez modifier ou supprimer des données stockées dans SharedPreferences. Pour modifier, utilisez simplement set* avec la même clé. Pour supprimer, utilisez remove() ou clear().
✏️ Modifier une valeur
Pour modifier une valeur existante, il suffit d'utiliser la même méthode set* avec la même clé. La valeur sera automatiquement remplacée.
📝 Syntaxe
// Modifier une valeur existante
// Si la clé existe déjà , la valeur sera remplacée
await prefs.setString('username', 'new_username');
await prefs.setInt('score', 1500); // Remplace l'ancien score
Analysons cette syntaxe :
setString('username', 'new_username'): Remplace la valeur de la clé 'username'- Si la clé n'existe pas, elle sera créée
- Si la clé existe, sa valeur sera remplacée
🗑️ Supprimer une clé
Pour supprimer une clé spécifique, utilisez la méthode remove() :
// Supprimer une clé spécifique
bool success = await prefs.remove('username');
if (success) {
print('Clé supprimée avec succès');
} else {
print('Erreur lors de la suppression');
}
🧹 Supprimer toutes les données
Pour supprimer toutes les données stockées, utilisez la méthode clear() :
// Supprimer toutes les données
bool success = await prefs.clear();
if (success) {
print('Toutes les données ont été supprimées');
} else {
print('Erreur lors de la suppression');
}
La méthode
clear() supprime toutes les données. Utilisez-la avec précaution, par exemple lors d'une déconnexion utilisateur ou d'une réinitialisation de l'application.
🧪 Exemple : Modifier et supprimer des préférences
Voici un exemple complet qui montre comment modifier et supprimer des préférences :
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() {
runApp(const MonApp());
}
class MonApp extends StatelessWidget {
const MonApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: const MaPage(),
);
}
}
class MaPage extends StatefulWidget {
const MaPage({super.key});
@override
State<MaPage> createState() => _MaPageState();
}
class _MaPageState extends State<MaPage> {
int score = 0;
@override
void initState() {
super.initState();
chargerScore();
}
Future<void> chargerScore() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
score = prefs.getInt('score') ?? 0;
});
}
Future<void> augmenterScore() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
// Récupérer le score actuel
int scoreActuel = prefs.getInt('score') ?? 0;
// Modifier le score (augmenter de 10)
await prefs.setInt('score', scoreActuel + 10);
// Recharger l'affichage
chargerScore();
}
Future<void> supprimerScore() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
// Supprimer la clé 'score'
await prefs.remove('score');
// Recharger l'affichage
chargerScore();
}
Future<void> reinitialiserTout() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
// Supprimer toutes les données
await prefs.clear();
// Recharger l'affichage
chargerScore();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Modifier et supprimer'),
),
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
Text(
'Score actuel : $score',
style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
const SizedBox(height: 24),
ElevatedButton(
onPressed: augmenterScore,
child: const Text('Augmenter le score (+10)'),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: supprimerScore,
style: ElevatedButton.styleFrom(
backgroundColor: Colors.orange,
),
child: const Text('Supprimer le score'),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: reinitialiserTout,
style: ElevatedButton.styleFrom(
backgroundColor: Colors.red,
),
child: const Text('Réinitialiser tout'),
),
],
),
),
),
);
}
}
Dans cet exemple :
- Le score est chargé au démarrage
- Le bouton "Augmenter le score" modifie la valeur existante
- Le bouton "Supprimer le score" supprime uniquement la clé 'score'
- Le bouton "Réinitialiser tout" supprime toutes les données
Il est recommandé de vérifier si une clé existe avant de la supprimer :
if (prefs.containsKey('username')) {
await prefs.remove('username');
print('Username supprimé');
} else {
print('La clé username n\'existe pas');
}
Pour modifier une valeur, vous n'avez pas besoin de la supprimer d'abord. Utilisez directement
set* avec la nouvelle valeur. La suppression n'est nécessaire que si vous voulez vraiment retirer une clé.
5.1.6 – Cas d'utilisation et limites
✅ Cas d'utilisation idéaux
1. Préférences utilisateur
SharedPreferences est parfait pour stocker les préférences de l'utilisateur :
// Exemple : Gestion du thème
Future<void> saveTheme(bool isDark) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setBool('isDarkMode', isDark);
}
Future<bool> loadTheme() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getBool('isDarkMode') ?? false;
}
2. Paramètres de l'application
Stocker des paramètres comme la langue, le volume, etc. :
// Exemple : Paramètres de langue et volume
Future<void> saveSettings(String language, double volume) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setString('language', language);
await prefs.setDouble('volume', volume);
}
3. Compteurs et statistiques simples
Pour suivre des compteurs ou des statistiques simples :
// Exemple : Compter les ouvertures de l'application
Future<void> incrementAppOpens() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
int opens = prefs.getInt('appOpens') ?? 0;
await prefs.setInt('appOpens', opens + 1);
}
4. Données de session non sensibles
Pour stocker des données de session simples (mais pas de mots de passe ou tokens sensibles) :
// Exemple : Nom d'utilisateur (non sensible)
Future<void> saveUsername(String username) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setString('username', username);
}
❌ Limites et cas à éviter
1. Données sensibles
- Mots de passe
- Tokens d'authentification sensibles
- Numéros de carte bancaire
- Toute donnée personnelle sensible
2. Grandes quantités de données
SharedPreferences n'est pas adapté pour stocker beaucoup de données :
- Plus de 100-200 clés : les performances peuvent se dégrader
- Données volumineuses : chaque clé ne devrait pas dépasser quelques KB
- Données fréquemment modifiées : chaque modification écrit sur le disque
3. Données relationnelles
Si vous avez besoin de relations entre données, utilisez une base de données :
- Liste d'utilisateurs avec relations (utilisateur → commandes → produits)
- Données nécessitant des requêtes complexes
- Données nécessitant des jointures
4. Données nécessitant des requêtes
SharedPreferences ne permet pas de faire des recherches ou filtres :
- Pas de recherche par valeur (seulement par clé)
- Pas de tri
- Pas de filtrage
📊 Tableau comparatif
Légende : ✓✓✓ Excellent | ✓✓ Très bon | ✓ Bon | ✗ Faible
🤔 Quand choisir SharedPreferences ?
âś… Utilisez SharedPreferences si :
- Vous avez besoin de stocker moins de 100-200 clés
- Vous stockez des types primitifs (String, int, bool, double)
- Vous n'avez pas besoin de requĂŞtes complexes
- Les données ne sont pas sensibles
- Vous voulez une solution simple et rapide
- Vous stockez des préférences utilisateur
❌ Utilisez une autre solution si :
- Vous avez des données sensibles (utilisez Secure Storage)
- Vous avez beaucoup de données (utilisez SQLite)
- Vous avez besoin de requĂŞtes complexes (utilisez SQLite)
- Vous avez des relations entre données (utilisez SQLite)
- Vous stockez des objets complexes (utilisez SQLite ou Hive)
Si vous hésitez entre SharedPreferences et une autre solution, posez-vous ces questions :
- Est-ce que j'ai moins de 200 clés ? → SharedPreferences
- Est-ce que les données sont sensibles ? → Secure Storage
- Est-ce que j'ai besoin de requêtes ? → SQLite
- Est-ce que j'ai des objets complexes ? → SQLite ou Hive
Maintenant que vous maîtrisez SharedPreferences, mettez vos connaissances en pratique avec l'exercice ci-dessous ! Vous allez créer une page de paramètres complète avec persistance des données.
🎯 Exercice pratique
Objectif : Créer une page de paramètres complète avec persistance des données en utilisant SharedPreferences. L'application doit permettre de configurer l'apparence (mode sombre, thème de couleur), les notifications (activation et types), la langue et la taille de police. Toutes les modifications doivent être automatiquement sauvegardées et restaurées au redémarrage de l'application.
📝 Instructions :
- Identifiez les défis : Observez l'interface et notez les défis techniques (par exemple : "Comment charger les paramètres au démarrage ?", "Comment sauvegarder automatiquement chaque modification ?", "Comment gérer le mode sombre avec SharedPreferences ?", etc.)
- Notez vos solutions : Avant de regarder le code, essayez de noter comment vous résoudriez chaque défi avec SharedPreferences (chargement dans initState(), sauvegarde dans onChanged, etc.)
- Comparez avec les solutions : Cliquez sur "Afficher le code" ci-dessous pour voir les solutions proposées et comparer avec vos notes. Analysez comment chaque paramètre est chargé et sauvegardé.
- Chargement au démarrage :
_chargerParametres()est appelé dansinitState()pour restaurer tous les paramètres sauvegardés - Sauvegarde automatique : Chaque modification (Switch, Radio, Checkbox, Dropdown) appelle immédiatement
_sauvegarder()pour persister la valeur - Fonction générique :
_sauvegarder()détecte automatiquement le type (bool ou String) et utilise la méthode appropriée - Réinitialisation : Le bouton "Réinitialiser" utilise
clear()pour supprimer toutes les données, puis recharge les valeurs par défaut - Mode sombre dynamique : Le mode sombre change immédiatement l'apparence de l'application et est sauvegardé pour être restauré au prochain démarrage