Choisir où réside l’état
Fait partie de la section Gestion d’état du Journey Flutter de Coddy. Leçon 21 sur 27.
L’interrupteur du mode sombre sur l’écran des paramètres bouge, mais rien ne passe en sombre. Il conserve sa valeur avec setState, et seul l’interrupteur peut la voir. Le thème est défini bien plus loin, dans MyApp. Cette valeur concerne toute l’application.
Chaque valeur d’une application a besoin d’un emplacement. Demande-toi qui l’utilise :
- Un seul widget (le texte d’un champ, un panneau ouvert, l’index d’un onglet) :
setStatedans ce widget. - Quelques widgets proches (un bouton et le libellé juste à côté) : remonte-la jusqu’à leur parent et transmets-la.
- De nombreux widgets ou plusieurs écrans (l’utilisateur, un panier, les paramètres) : un modèle partagé avec Provider ou Riverpod.
Provider ou Riverpod ? Les deux font l’affaire. Provider est un peu plus simple et place les modèles dans l’arbre des widgets, où ils sont accessibles via context. Riverpod conserve les providers en dehors de l’arbre, ainsi une valeur n’a pas besoin de context, et les providers peuvent s’observer entre eux. Choisis-en un pour une application et utilise-le partout.
Ici, un StateProvider convient : un bool, lu par MyApp pour choisir le thème et modifié par l’interrupteur :
final darkModeProvider = StateProvider((ref) => false);
// dans MyApp, désormais un ConsumerWidget :
themeMode: ref.watch(darkModeProvider) ? ThemeMode.dark : ThemeMode.light,Défi
DifficileFais en sorte que le commutateur du mode sombre modifie toute l’application :
- Ajoute
final darkModeProvider = StateProvider((ref) => false);en haut. - Transforme
MyAppenConsumerWidgetdont lethemeModesuit le fournisseur. - Transforme
SettingsScreenenConsumerWidget: le commutateur affiche la valeur du fournisseur et la définit lorsqu’il est actionné.
Essayez vous-même
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
void main() {
runApp(const ProviderScope(child: MyApp()));
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData.light(),
darkTheme: ThemeData.dark(),
themeMode: ThemeMode.light,
home: const HomePage(),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Notes'),
actions: [
IconButton(
icon: const Icon(Icons.settings),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const SettingsScreen()),
);
},
),
],
),
body: const Center(child: Text('No notes yet')),
);
}
}
class SettingsScreen extends StatefulWidget {
const SettingsScreen({super.key});
@override
State<SettingsScreen> createState() => _SettingsScreenState();
}
class _SettingsScreenState extends State<SettingsScreen> {
bool dark = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Settings')),
body: ListView(
children: [
SwitchListTile(
title: const Text('Dark mode'),
value: dark,
onChanged: (value) {
setState(() {
dark = value;
});
},
),
],
),
);
}
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Gestion d’état
Entraînez-vous par vous-même : Compilateur Flutter en ligne