Riverpod: Notifier
Część sekcji Zarządzanie stanem ścieżki Flutter w Coddy. Lekcja 19 z 27.
Do jednej liczby wystarczy StateProvider. Gdy stan podlega regułom, na przykład gdy jest listą z metodami dodawania i usuwania elementów, napisz Notifier: klasę, która przechowuje stan i metody, które go zmieniają.
class GuestList extends Notifier<List<String>> {
@override
List<String> build() => [];
void add(String name) {
state = [...state, name];
}
}
final guestsProvider =
NotifierProvider<GuestList, List<String>>(GuestList.new);build zwraca pierwszy stan — pustą listę. Wewnątrz klasy state oznacza bieżącą wartość. GuestList.new to konstruktor klasy przekazywany dostawcy, aby mógł utworzyć powiadamiacz.
Najważniejsza zasada: przypisuj state nową wartość, nigdy nie zmieniaj starej. Riverpod powiadamia widżety tylko wtedy, gdy do state zostanie przypisany inny obiekt. state.add(name) zmienia listę w miejscu, więc state nadal wskazuje tę samą listę i nikt się o tym nie dowiaduje. [...state, name] tworzy nową listę: trzy kropki rozpakowują do niej wszystkie poprzednie imiona, a potem na końcu dodawane jest nowe.
Widżet wywołuje metodę za pośrednictwem powiadamiacza: ref.read(guestsProvider.notifier).add('Ada'). Ta strona używa ConsumerStatefulWidget, czyli widżetu ze stanem, ponieważ przechowuje również kontroler tekstu. Jego State ma pole ref.
Wyzwanie
TrudnyLista gości wyświetla nazwy z guestsProvider, ale Add tylko czyści pole.
- Dodaj metodę
add(String name)doGuestList, która ustawiastatena nową listę z nazwą na końcu. - Spraw, aby
Addwywoływało tę metodę z tekstem z pola, zanim je wyczyści.
Spróbuj swoich sił
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
class GuestList extends Notifier<List<String>> {
@override
List<String> build() => [];
}
final guestsProvider = NotifierProvider<GuestList, List<String>>(GuestList.new);
void main() {
runApp(const ProviderScope(child: MyApp()));
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: PartyPage(),
);
}
}
class PartyPage extends ConsumerStatefulWidget {
const PartyPage({super.key});
@override
ConsumerState<PartyPage> createState() => _PartyPageState();
}
class _PartyPageState extends ConsumerState<PartyPage> {
final controller = TextEditingController();
@override
Widget build(BuildContext context) {
final guests = ref.watch(guestsProvider);
return Scaffold(
appBar: AppBar(title: Text('Guests: ${guests.length}')),
body: Column(
children: [
Padding(
padding: const EdgeInsets.all(16),
child: Row(
children: [
Expanded(
child: TextField(
controller: controller,
decoration: const InputDecoration(labelText: 'Guest name'),
),
),
const SizedBox(width: 8),
ElevatedButton(
onPressed: () {
controller.clear();
},
child: const Text('Add'),
),
],
),
),
Expanded(
child: ListView(
children: [
for (final name in guests) ListTile(leading: const Icon(Icons.person), title: Text(name)),
],
),
),
],
),
);
}
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Zarządzanie stanem
Poćwicz samodzielnie: Kompilator Flutter online